Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
This commit is contained in:
@@ -23,7 +23,8 @@ config USB_ARCH_HAS_OHCI
|
||||
default y if ARCH_LH7A404
|
||||
default y if ARCH_S3C2410
|
||||
default y if PXA27x
|
||||
default y if ARCH_AT91RM9200
|
||||
default y if ARCH_EP93XX
|
||||
default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
|
||||
# PPC:
|
||||
default y if STB03xxx
|
||||
default y if PPC_MPC52xx
|
||||
|
||||
@@ -48,7 +48,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/
|
||||
obj-$(CONFIG_USB_SERIAL) += serial/
|
||||
|
||||
obj-$(CONFIG_USB_AUERSWALD) += misc/
|
||||
obj-$(CONFIG_USB_CY7C63) += misc/
|
||||
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
|
||||
obj-$(CONFIG_USB_CYTHERM) += misc/
|
||||
obj-$(CONFIG_USB_EMI26) += misc/
|
||||
obj-$(CONFIG_USB_EMI62) += misc/
|
||||
|
||||
@@ -291,13 +291,13 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
|
||||
struct acm_ru *rcv = urb->context;
|
||||
struct acm *acm = rcv->instance;
|
||||
int status = urb->status;
|
||||
dbg("Entering acm_read_bulk with status %d\n", urb->status);
|
||||
dbg("Entering acm_read_bulk with status %d", urb->status);
|
||||
|
||||
if (!ACM_READY(acm))
|
||||
return;
|
||||
|
||||
if (status)
|
||||
dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
|
||||
dev_dbg(&acm->data->dev, "bulk rx status %d", status);
|
||||
|
||||
buf = rcv->buffer;
|
||||
buf->size = urb->actual_length;
|
||||
@@ -343,7 +343,7 @@ next_buffer:
|
||||
list_del(&buf->list);
|
||||
spin_unlock(&acm->read_lock);
|
||||
|
||||
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
|
||||
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
|
||||
|
||||
tty_buffer_request_room(tty, buf->size);
|
||||
if (!acm->throttle)
|
||||
@@ -394,7 +394,7 @@ urbs:
|
||||
rcv->urb->transfer_dma = buf->dma;
|
||||
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
|
||||
dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
|
||||
|
||||
/* This shouldn't kill the driver as unsuccessful URBs are returned to the
|
||||
free-urbs-pool and resubmited ASAP */
|
||||
@@ -413,7 +413,7 @@ static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct acm *acm = (struct acm *)urb->context;
|
||||
|
||||
dbg("Entering acm_write_bulk with status %d\n", urb->status);
|
||||
dbg("Entering acm_write_bulk with status %d", urb->status);
|
||||
|
||||
acm_write_done(acm);
|
||||
acm_write_start(acm);
|
||||
@@ -424,7 +424,7 @@ static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
|
||||
static void acm_softint(void *private)
|
||||
{
|
||||
struct acm *acm = private;
|
||||
dbg("Entering acm_softint.\n");
|
||||
dbg("Entering acm_softint.");
|
||||
|
||||
if (!ACM_READY(acm))
|
||||
return;
|
||||
@@ -440,7 +440,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
struct acm *acm;
|
||||
int rv = -EINVAL;
|
||||
int i;
|
||||
dbg("Entering acm_tty_open.\n");
|
||||
dbg("Entering acm_tty_open.");
|
||||
|
||||
mutex_lock(&open_mutex);
|
||||
|
||||
@@ -541,7 +541,7 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
|
||||
int wbn;
|
||||
struct acm_wb *wb;
|
||||
|
||||
dbg("Entering acm_tty_write to write %d bytes,\n", count);
|
||||
dbg("Entering acm_tty_write to write %d bytes,", count);
|
||||
|
||||
if (!ACM_READY(acm))
|
||||
return -EINVAL;
|
||||
@@ -793,7 +793,7 @@ static int acm_probe (struct usb_interface *intf,
|
||||
|
||||
if (!buflen) {
|
||||
if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
|
||||
dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n");
|
||||
dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint");
|
||||
buflen = intf->cur_altsetting->endpoint->extralen;
|
||||
buffer = intf->cur_altsetting->endpoint->extra;
|
||||
} else {
|
||||
@@ -842,24 +842,24 @@ next_desc:
|
||||
|
||||
if (!union_header) {
|
||||
if (call_interface_num > 0) {
|
||||
dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
|
||||
dev_dbg(&intf->dev,"No union descriptor, using call management descriptor");
|
||||
data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
|
||||
control_interface = intf;
|
||||
} else {
|
||||
dev_dbg(&intf->dev,"No union descriptor, giving up\n");
|
||||
dev_dbg(&intf->dev,"No union descriptor, giving up");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
|
||||
data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
|
||||
if (!control_interface || !data_interface) {
|
||||
dev_dbg(&intf->dev,"no interfaces\n");
|
||||
dev_dbg(&intf->dev,"no interfaces");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (data_interface_num != call_interface_num)
|
||||
dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");
|
||||
dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
|
||||
|
||||
skip_normal_probe:
|
||||
|
||||
@@ -867,7 +867,7 @@ skip_normal_probe:
|
||||
if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
|
||||
if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
|
||||
struct usb_interface *t;
|
||||
dev_dbg(&intf->dev,"Your device has switched interfaces.\n");
|
||||
dev_dbg(&intf->dev,"Your device has switched interfaces.");
|
||||
|
||||
t = control_interface;
|
||||
control_interface = data_interface;
|
||||
@@ -878,7 +878,7 @@ skip_normal_probe:
|
||||
}
|
||||
|
||||
if (usb_interface_claimed(data_interface)) { /* valid in this context */
|
||||
dev_dbg(&intf->dev,"The data interface isn't available\n");
|
||||
dev_dbg(&intf->dev,"The data interface isn't available");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@@ -895,7 +895,7 @@ skip_normal_probe:
|
||||
if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
|
||||
/* descriptors are swapped */
|
||||
struct usb_endpoint_descriptor *t;
|
||||
dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
|
||||
dev_dbg(&intf->dev,"The data interface has switched endpoints");
|
||||
|
||||
t = epread;
|
||||
epread = epwrite;
|
||||
@@ -910,7 +910,7 @@ skip_normal_probe:
|
||||
}
|
||||
|
||||
if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
|
||||
dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
|
||||
dev_dbg(&intf->dev, "out of memory (acm kzalloc)");
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
@@ -936,26 +936,26 @@ skip_normal_probe:
|
||||
|
||||
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
|
||||
if (!buf) {
|
||||
dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
|
||||
dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)");
|
||||
goto alloc_fail2;
|
||||
}
|
||||
acm->ctrl_buffer = buf;
|
||||
|
||||
if (acm_write_buffers_alloc(acm) < 0) {
|
||||
dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
|
||||
dev_dbg(&intf->dev, "out of memory (write buffer alloc)");
|
||||
goto alloc_fail4;
|
||||
}
|
||||
|
||||
acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!acm->ctrlurb) {
|
||||
dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
|
||||
dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)");
|
||||
goto alloc_fail5;
|
||||
}
|
||||
for (i = 0; i < num_rx_buf; i++) {
|
||||
struct acm_ru *rcv = &(acm->ru[i]);
|
||||
|
||||
if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
|
||||
dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
|
||||
dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)");
|
||||
goto alloc_fail7;
|
||||
}
|
||||
|
||||
@@ -966,13 +966,13 @@ skip_normal_probe:
|
||||
struct acm_rb *buf = &(acm->rb[i]);
|
||||
|
||||
if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
|
||||
dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
|
||||
dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)");
|
||||
goto alloc_fail7;
|
||||
}
|
||||
}
|
||||
acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!acm->writeurb) {
|
||||
dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
|
||||
dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)");
|
||||
goto alloc_fail7;
|
||||
}
|
||||
|
||||
@@ -1086,6 +1086,9 @@ static struct usb_device_id acm_ids[] = {
|
||||
{ USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */
|
||||
.driver_info = SINGLE_RX_URB, /* firmware bug */
|
||||
},
|
||||
{ USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
|
||||
.driver_info = SINGLE_RX_URB, /* firmware bug */
|
||||
},
|
||||
/* control interfaces with various AT-command sets */
|
||||
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
|
||||
USB_CDC_ACM_PROTO_AT_V25TER) },
|
||||
|
||||
@@ -31,9 +31,6 @@ config USB_DEVICEFS
|
||||
For the format of the various /proc/bus/usb/ files, please read
|
||||
<file:Documentation/usb/proc_usb_info.txt>.
|
||||
|
||||
Please note that this code is completely unrelated to devfs, the
|
||||
"/dev file system support".
|
||||
|
||||
Most users want to say Y here.
|
||||
|
||||
config USB_BANDWIDTH
|
||||
|
||||
@@ -517,19 +517,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
|
||||
|
||||
static struct usb_device *usbdev_lookup_minor(int minor)
|
||||
{
|
||||
struct device *device;
|
||||
struct usb_device *udev = NULL;
|
||||
struct class_device *class_dev;
|
||||
struct usb_device *dev = NULL;
|
||||
|
||||
down(&usb_device_class->sem);
|
||||
list_for_each_entry(device, &usb_device_class->devices, node) {
|
||||
if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
|
||||
udev = device->platform_data;
|
||||
list_for_each_entry(class_dev, &usb_device_class->children, node) {
|
||||
if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
|
||||
dev = class_dev->class_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&usb_device_class->sem);
|
||||
|
||||
return udev;
|
||||
return dev;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1580,16 +1580,16 @@ static void usbdev_add(struct usb_device *dev)
|
||||
{
|
||||
int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
|
||||
|
||||
dev->usbfs_dev = device_create(usb_device_class, &dev->dev,
|
||||
MKDEV(USB_DEVICE_MAJOR, minor),
|
||||
dev->class_dev = class_device_create(usb_device_class, NULL,
|
||||
MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
|
||||
"usbdev%d.%d", dev->bus->busnum, dev->devnum);
|
||||
|
||||
dev->usbfs_dev->platform_data = dev;
|
||||
dev->class_dev->class_data = dev;
|
||||
}
|
||||
|
||||
static void usbdev_remove(struct usb_device *dev)
|
||||
{
|
||||
device_unregister(dev->usbfs_dev);
|
||||
class_device_unregister(dev->class_dev);
|
||||
}
|
||||
|
||||
static int usbdev_notify(struct notifier_block *self, unsigned long action,
|
||||
|
||||
@@ -194,13 +194,14 @@ int usb_register_dev(struct usb_interface *intf,
|
||||
++temp;
|
||||
else
|
||||
temp = name;
|
||||
intf->usb_dev = device_create(usb_class->class, &intf->dev,
|
||||
MKDEV(USB_MAJOR, minor), "%s", temp);
|
||||
if (IS_ERR(intf->usb_dev)) {
|
||||
intf->class_dev = class_device_create(usb_class->class, NULL,
|
||||
MKDEV(USB_MAJOR, minor),
|
||||
&intf->dev, "%s", temp);
|
||||
if (IS_ERR(intf->class_dev)) {
|
||||
spin_lock (&minor_lock);
|
||||
usb_minors[intf->minor] = NULL;
|
||||
spin_unlock (&minor_lock);
|
||||
retval = PTR_ERR(intf->usb_dev);
|
||||
retval = PTR_ERR(intf->class_dev);
|
||||
}
|
||||
exit:
|
||||
return retval;
|
||||
@@ -241,8 +242,8 @@ void usb_deregister_dev(struct usb_interface *intf,
|
||||
spin_unlock (&minor_lock);
|
||||
|
||||
snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
|
||||
device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
|
||||
intf->usb_dev = NULL;
|
||||
class_device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
|
||||
intf->class_dev = NULL;
|
||||
intf->minor = -1;
|
||||
destroy_usb_class();
|
||||
}
|
||||
|
||||
@@ -1790,7 +1790,10 @@ static int finish_device_resume(struct usb_device *udev)
|
||||
* and device drivers will know about any resume quirks.
|
||||
*/
|
||||
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
|
||||
if (status < 2)
|
||||
if (status >= 0)
|
||||
status = (status == 2 ? 0 : -ENODEV);
|
||||
|
||||
if (status)
|
||||
dev_dbg(&udev->dev,
|
||||
"gone after usb resume? status %d\n",
|
||||
status);
|
||||
@@ -1879,7 +1882,12 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
|
||||
dev_dbg(hub->intfdev,
|
||||
"port %d status %04x.%04x after resume, %d\n",
|
||||
port1, portchange, devstatus, status);
|
||||
if (status >= 0)
|
||||
status = -ENODEV;
|
||||
} else {
|
||||
if (portchange & USB_PORT_STAT_C_SUSPEND)
|
||||
clear_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_C_SUSPEND);
|
||||
/* TRSMRCY = 10 msec */
|
||||
msleep(10);
|
||||
if (udev)
|
||||
|
||||
@@ -695,7 +695,7 @@ static void usbfs_remove_device(struct usb_device *dev)
|
||||
wake_up_all(&ds->wait);
|
||||
list_del_init(&ds->list);
|
||||
if (ds->discsignr) {
|
||||
sinfo.si_signo = SIGPIPE;
|
||||
sinfo.si_signo = ds->discsignr;
|
||||
sinfo.si_errno = EPIPE;
|
||||
sinfo.si_code = SI_ASYNCIO;
|
||||
sinfo.si_addr = ds->disccontext;
|
||||
|
||||
@@ -207,7 +207,7 @@ config USB_AT91
|
||||
|
||||
config USB_GADGET_DUMMY_HCD
|
||||
boolean "Dummy HCD (DEVELOPMENT)"
|
||||
depends on USB && EXPERIMENTAL
|
||||
depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
This host controller driver emulates USB, looping all data transfer
|
||||
|
||||
@@ -57,19 +57,23 @@
|
||||
|
||||
/*
|
||||
* This controller is simple and PIO-only. It's used in many AT91-series
|
||||
* ARMv4T controllers, including the at91rm9200 (arm920T, with MMU),
|
||||
* at91sam9261 (arm926ejs, with MMU), and several no-mmu versions.
|
||||
* full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
|
||||
* at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
|
||||
*
|
||||
* This driver expects the board has been wired with two GPIOs suppporting
|
||||
* a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the
|
||||
* testing hasn't covered such cases.) The pullup is most important; it
|
||||
* testing hasn't covered such cases.)
|
||||
*
|
||||
* The pullup is most important (so it's integrated on sam926x parts). It
|
||||
* provides software control over whether the host enumerates the device.
|
||||
*
|
||||
* The VBUS sensing helps during enumeration, and allows both USB clocks
|
||||
* (and the transceiver) to stay gated off until they're necessary, saving
|
||||
* power. During USB suspend, the 48 MHz clock is gated off.
|
||||
* power. During USB suspend, the 48 MHz clock is gated off in hardware;
|
||||
* it may also be gated off by software during some Linux sleep states.
|
||||
*/
|
||||
|
||||
#define DRIVER_VERSION "8 March 2005"
|
||||
#define DRIVER_VERSION "3 May 2006"
|
||||
|
||||
static const char driver_name [] = "at91_udc";
|
||||
static const char ep0name[] = "ep0";
|
||||
@@ -316,9 +320,15 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status)
|
||||
*
|
||||
* There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE
|
||||
* that shouldn't normally be changed.
|
||||
*
|
||||
* NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains,
|
||||
* implying a need to wait for one write to complete (test relevant bits)
|
||||
* before starting the next write. This shouldn't be an issue given how
|
||||
* infrequently we write, except maybe for write-then-read idioms.
|
||||
*/
|
||||
#define SET_FX (AT91_UDP_TXPKTRDY)
|
||||
#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
|
||||
#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP \
|
||||
| AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
|
||||
|
||||
/* pull OUT packet data from the endpoint's fifo */
|
||||
static int read_fifo (struct at91_ep *ep, struct at91_request *req)
|
||||
@@ -472,7 +482,8 @@ static void nuke(struct at91_ep *ep, int status)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
|
||||
static int at91_ep_enable(struct usb_ep *_ep,
|
||||
const struct usb_endpoint_descriptor *desc)
|
||||
{
|
||||
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
|
||||
struct at91_udc *dev = ep->udc;
|
||||
@@ -582,11 +593,12 @@ static int at91_ep_disable (struct usb_ep * _ep)
|
||||
* interesting for request or buffer allocation.
|
||||
*/
|
||||
|
||||
static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags)
|
||||
static struct usb_request *
|
||||
at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags)
|
||||
{
|
||||
struct at91_request *req;
|
||||
|
||||
req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL);
|
||||
req = kcalloc(1, sizeof (struct at91_request), gfp_flags);
|
||||
if (!req)
|
||||
return NULL;
|
||||
|
||||
@@ -862,6 +874,7 @@ static void stop_activity(struct at91_udc *udc)
|
||||
if (udc->gadget.speed == USB_SPEED_UNKNOWN)
|
||||
driver = NULL;
|
||||
udc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||
udc->suspended = 0;
|
||||
|
||||
for (i = 0; i < NUM_ENDPOINTS; i++) {
|
||||
struct at91_ep *ep = &udc->ep[i];
|
||||
@@ -889,8 +902,8 @@ static void clk_off(struct at91_udc *udc)
|
||||
return;
|
||||
udc->clocked = 0;
|
||||
udc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||
clk_disable(udc->iclk);
|
||||
clk_disable(udc->fclk);
|
||||
clk_disable(udc->iclk);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -911,9 +924,6 @@ static void pullup(struct at91_udc *udc, int is_on)
|
||||
at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
|
||||
at91_set_gpio_value(udc->board.pullup_pin, 0);
|
||||
clk_off(udc);
|
||||
|
||||
// REVISIT: with transceiver disabled, will D- float
|
||||
// so that a host would falsely detect a device?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,7 +1300,8 @@ static void handle_ep0(struct at91_udc *udc)
|
||||
if (udc->wait_for_addr_ack) {
|
||||
u32 tmp;
|
||||
|
||||
at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr);
|
||||
at91_udp_write(AT91_UDP_FADDR,
|
||||
AT91_UDP_FEN | udc->addr);
|
||||
tmp = at91_udp_read(AT91_UDP_GLB_STAT);
|
||||
tmp &= ~AT91_UDP_FADDEN;
|
||||
if (udc->addr)
|
||||
@@ -1361,9 +1372,10 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r)
|
||||
u32 rescans = 5;
|
||||
|
||||
while (rescans--) {
|
||||
u32 status = at91_udp_read(AT91_UDP_ISR);
|
||||
u32 status;
|
||||
|
||||
status &= at91_udp_read(AT91_UDP_IMR);
|
||||
status = at91_udp_read(AT91_UDP_ISR)
|
||||
& at91_udp_read(AT91_UDP_IMR);
|
||||
if (!status)
|
||||
break;
|
||||
|
||||
@@ -1379,18 +1391,17 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r)
|
||||
stop_activity(udc);
|
||||
|
||||
/* enable ep0 */
|
||||
at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
|
||||
at91_udp_write(AT91_UDP_CSR(0),
|
||||
AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
|
||||
udc->gadget.speed = USB_SPEED_FULL;
|
||||
udc->suspended = 0;
|
||||
at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0));
|
||||
|
||||
/*
|
||||
* NOTE: this driver keeps clocks off unless the
|
||||
* USB host is present. That saves power, and also
|
||||
* eliminates IRQs (reset, resume, suspend) that can
|
||||
* otherwise flood from the controller. If your
|
||||
* board doesn't support VBUS detection, suspend and
|
||||
* resume irq logic may need more attention...
|
||||
* USB host is present. That saves power, but for
|
||||
* boards that don't support VBUS detection, both
|
||||
* clocks need to be active most of the time.
|
||||
*/
|
||||
|
||||
/* host initiated suspend (3+ms bus idle) */
|
||||
@@ -1452,13 +1463,19 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void nop_release(struct device *dev)
|
||||
{
|
||||
/* nothing to free */
|
||||
}
|
||||
|
||||
static struct at91_udc controller = {
|
||||
.gadget = {
|
||||
.ops = &at91_udc_ops,
|
||||
.ep0 = &controller.ep[0].ep,
|
||||
.name = driver_name,
|
||||
.dev = {
|
||||
.bus_id = "gadget"
|
||||
.ops = &at91_udc_ops,
|
||||
.ep0 = &controller.ep[0].ep,
|
||||
.name = driver_name,
|
||||
.dev = {
|
||||
.bus_id = "gadget",
|
||||
.release = nop_release,
|
||||
}
|
||||
},
|
||||
.ep[0] = {
|
||||
@@ -1468,7 +1485,8 @@ static struct at91_udc controller = {
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 8,
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)),
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP
|
||||
+ AT91_UDP_CSR(0)),
|
||||
.int_mask = 1 << 0,
|
||||
},
|
||||
.ep[1] = {
|
||||
@@ -1479,7 +1497,8 @@ static struct at91_udc controller = {
|
||||
.udc = &controller,
|
||||
.is_pingpong = 1,
|
||||
.maxpacket = 64,
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)),
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP
|
||||
+ AT91_UDP_CSR(1)),
|
||||
.int_mask = 1 << 1,
|
||||
},
|
||||
.ep[2] = {
|
||||
@@ -1490,7 +1509,8 @@ static struct at91_udc controller = {
|
||||
.udc = &controller,
|
||||
.is_pingpong = 1,
|
||||
.maxpacket = 64,
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)),
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP
|
||||
+ AT91_UDP_CSR(2)),
|
||||
.int_mask = 1 << 2,
|
||||
},
|
||||
.ep[3] = {
|
||||
@@ -1501,7 +1521,8 @@ static struct at91_udc controller = {
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 8,
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)),
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP
|
||||
+ AT91_UDP_CSR(3)),
|
||||
.int_mask = 1 << 3,
|
||||
},
|
||||
.ep[4] = {
|
||||
@@ -1512,7 +1533,8 @@ static struct at91_udc controller = {
|
||||
.udc = &controller,
|
||||
.is_pingpong = 1,
|
||||
.maxpacket = 256,
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)),
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP
|
||||
+ AT91_UDP_CSR(4)),
|
||||
.int_mask = 1 << 4,
|
||||
},
|
||||
.ep[5] = {
|
||||
@@ -1523,10 +1545,11 @@ static struct at91_udc controller = {
|
||||
.udc = &controller,
|
||||
.is_pingpong = 1,
|
||||
.maxpacket = 256,
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)),
|
||||
.creg = (void __iomem *)(AT91_VA_BASE_UDP
|
||||
+ AT91_UDP_CSR(5)),
|
||||
.int_mask = 1 << 5,
|
||||
},
|
||||
/* ep6 and ep7 are also reserved */
|
||||
/* ep6 and ep7 are also reserved (custom silicon might use them) */
|
||||
};
|
||||
|
||||
static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r)
|
||||
@@ -1593,6 +1616,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
|
||||
|
||||
local_irq_disable();
|
||||
udc->enabled = 0;
|
||||
at91_udp_write(AT91_UDP_IDR, ~0);
|
||||
pullup(udc, 0);
|
||||
local_irq_enable();
|
||||
|
||||
@@ -1624,6 +1648,16 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pdev->num_resources != 2) {
|
||||
DBG("invalid num_resources");
|
||||
return -ENODEV;
|
||||
}
|
||||
if ((pdev->resource[0].flags != IORESOURCE_MEM)
|
||||
|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
|
||||
DBG("invalid resource type");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) {
|
||||
DBG("someone's using UDC memory\n");
|
||||
return -EBUSY;
|
||||
@@ -1649,19 +1683,26 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
|
||||
if (retval < 0)
|
||||
goto fail0;
|
||||
|
||||
/* disable everything until there's a gadget driver and vbus */
|
||||
pullup(udc, 0);
|
||||
/* don't do anything until we have both gadget driver and VBUS */
|
||||
clk_enable(udc->iclk);
|
||||
at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
|
||||
at91_udp_write(AT91_UDP_IDR, 0xffffffff);
|
||||
clk_disable(udc->iclk);
|
||||
|
||||
/* request UDC and maybe VBUS irqs */
|
||||
if (request_irq(AT91_ID_UDP, at91_udc_irq, IRQF_DISABLED, driver_name, udc)) {
|
||||
DBG("request irq %d failed\n", AT91_ID_UDP);
|
||||
udc->udp_irq = platform_get_irq(pdev, 0);
|
||||
if (request_irq(udc->udp_irq, at91_udc_irq,
|
||||
IRQF_DISABLED, driver_name, udc)) {
|
||||
DBG("request irq %d failed\n", udc->udp_irq);
|
||||
retval = -EBUSY;
|
||||
goto fail1;
|
||||
}
|
||||
if (udc->board.vbus_pin > 0) {
|
||||
if (request_irq(udc->board.vbus_pin, at91_vbus_irq, IRQF_DISABLED, driver_name, udc)) {
|
||||
DBG("request vbus irq %d failed\n", udc->board.vbus_pin);
|
||||
free_irq(AT91_ID_UDP, udc);
|
||||
if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
|
||||
IRQF_DISABLED, driver_name, udc)) {
|
||||
DBG("request vbus irq %d failed\n",
|
||||
udc->board.vbus_pin);
|
||||
free_irq(udc->udp_irq, udc);
|
||||
retval = -EBUSY;
|
||||
goto fail1;
|
||||
}
|
||||
@@ -1670,6 +1711,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
|
||||
udc->vbus = 1;
|
||||
}
|
||||
dev_set_drvdata(dev, udc);
|
||||
device_init_wakeup(dev, 1);
|
||||
create_debug_file(udc);
|
||||
|
||||
INFO("%s version %s\n", driver_name, DRIVER_VERSION);
|
||||
@@ -1678,14 +1720,14 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
|
||||
fail1:
|
||||
device_unregister(&udc->gadget.dev);
|
||||
fail0:
|
||||
release_mem_region(AT91_VA_BASE_UDP, SZ_16K);
|
||||
release_mem_region(AT91_BASE_UDP, SZ_16K);
|
||||
DBG("%s probe failed, %d\n", driver_name, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int __devexit at91udc_remove(struct platform_device *dev)
|
||||
static int __devexit at91udc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct at91_udc *udc = platform_get_drvdata(dev);
|
||||
struct at91_udc *udc = platform_get_drvdata(pdev);
|
||||
|
||||
DBG("remove\n");
|
||||
|
||||
@@ -1694,10 +1736,11 @@ static int __devexit at91udc_remove(struct platform_device *dev)
|
||||
if (udc->driver != 0)
|
||||
usb_gadget_unregister_driver(udc->driver);
|
||||
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
remove_debug_file(udc);
|
||||
if (udc->board.vbus_pin > 0)
|
||||
free_irq(udc->board.vbus_pin, udc);
|
||||
free_irq(AT91_ID_UDP, udc);
|
||||
free_irq(udc->udp_irq, udc);
|
||||
device_unregister(&udc->gadget.dev);
|
||||
release_mem_region(AT91_BASE_UDP, SZ_16K);
|
||||
|
||||
@@ -1708,31 +1751,36 @@ static int __devexit at91udc_remove(struct platform_device *dev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg)
|
||||
static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
|
||||
{
|
||||
struct at91_udc *udc = platform_get_drvdata(dev);
|
||||
struct at91_udc *udc = platform_get_drvdata(pdev);
|
||||
int wake = udc->driver && device_may_wakeup(&pdev->dev);
|
||||
|
||||
/*
|
||||
* The "safe" suspend transitions are opportunistic ... e.g. when
|
||||
* the USB link is suspended (48MHz clock autogated off), or when
|
||||
* it's disconnected (programmatically gated off, elsewhere).
|
||||
* Then we can suspend, and the chip can enter slow clock mode.
|
||||
*
|
||||
* The problem case is some component (user mode?) suspending this
|
||||
* device while it's active, with the 48 MHz clock in use. There
|
||||
* are two basic approaches: (a) veto suspend levels involving slow
|
||||
* clock mode, (b) disconnect, so 48 MHz will no longer be in use
|
||||
* and we can enter slow clock mode. This uses (b) for now, since
|
||||
* it's simplest until AT91 PM exists and supports the other option.
|
||||
/* Unless we can act normally to the host (letting it wake us up
|
||||
* whenever it has work for us) force disconnect. Wakeup requires
|
||||
* PLLB for USB events (signaling for reset, wakeup, or incoming
|
||||
* tokens) and VBUS irqs (on systems which support them).
|
||||
*/
|
||||
if (udc->vbus && !udc->suspended)
|
||||
if ((!udc->suspended && udc->addr)
|
||||
|| !wake
|
||||
|| at91_suspend_entering_slow_clock()) {
|
||||
pullup(udc, 0);
|
||||
disable_irq_wake(udc->udp_irq);
|
||||
} else
|
||||
enable_irq_wake(udc->udp_irq);
|
||||
|
||||
if (udc->board.vbus_pin > 0) {
|
||||
if (wake)
|
||||
enable_irq_wake(udc->board.vbus_pin);
|
||||
else
|
||||
disable_irq_wake(udc->board.vbus_pin);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91udc_resume(struct platform_device *dev)
|
||||
static int at91udc_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct at91_udc *udc = platform_get_drvdata(dev);
|
||||
struct at91_udc *udc = platform_get_drvdata(pdev);
|
||||
|
||||
/* maybe reconnect to host; if so, clocks on */
|
||||
pullup(udc, 1);
|
||||
@@ -1748,7 +1796,7 @@ static struct platform_driver at91_udc = {
|
||||
.remove = __devexit_p(at91udc_remove),
|
||||
.shutdown = at91udc_shutdown,
|
||||
.suspend = at91udc_suspend,
|
||||
.resume = at91udc_resume,
|
||||
.resume = at91udc_resume,
|
||||
.driver = {
|
||||
.name = (char *) driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1767,6 +1815,6 @@ static void __devexit udc_exit_module(void)
|
||||
}
|
||||
module_exit(udc_exit_module);
|
||||
|
||||
MODULE_DESCRIPTION("AT91RM9200 udc driver");
|
||||
MODULE_DESCRIPTION("AT91 udc driver");
|
||||
MODULE_AUTHOR("Thomas Rathbone, David Brownell");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -141,6 +141,7 @@ struct at91_udc {
|
||||
struct clk *iclk, *fclk;
|
||||
struct platform_device *pdev;
|
||||
struct proc_dir_entry *pde;
|
||||
int udp_irq;
|
||||
};
|
||||
|
||||
static inline struct at91_udc *to_udc(struct usb_gadget *g)
|
||||
|
||||
@@ -609,7 +609,8 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
|
||||
if (!dum->driver)
|
||||
return -ESHUTDOWN;
|
||||
|
||||
spin_lock_irqsave (&dum->lock, flags);
|
||||
local_irq_save (flags);
|
||||
spin_lock (&dum->lock);
|
||||
list_for_each_entry (req, &ep->queue, queue) {
|
||||
if (&req->req == _req) {
|
||||
list_del_init (&req->queue);
|
||||
@@ -618,7 +619,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore (&dum->lock, flags);
|
||||
spin_unlock (&dum->lock);
|
||||
|
||||
if (retval == 0) {
|
||||
dev_dbg (udc_dev(dum),
|
||||
@@ -626,6 +627,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
|
||||
req, _ep->name, _req->length, _req->buf);
|
||||
_req->complete (_ep, _req);
|
||||
}
|
||||
local_irq_restore (flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@
|
||||
|
||||
|
||||
/* we must assign addresses for configurable endpoints (like net2280) */
|
||||
static __initdata unsigned epnum;
|
||||
static __devinitdata unsigned epnum;
|
||||
|
||||
// #define MANY_ENDPOINTS
|
||||
#ifdef MANY_ENDPOINTS
|
||||
/* more than 15 configurable endpoints */
|
||||
static __initdata unsigned in_epnum;
|
||||
static __devinitdata unsigned in_epnum;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ static __initdata unsigned in_epnum;
|
||||
* NOTE: each endpoint is unidirectional, as specified by its USB
|
||||
* descriptor; and isn't specific to a configuration or altsetting.
|
||||
*/
|
||||
static int __init
|
||||
static int __devinit
|
||||
ep_matches (
|
||||
struct usb_gadget *gadget,
|
||||
struct usb_ep *ep,
|
||||
@@ -73,7 +73,7 @@ ep_matches (
|
||||
/* endpoint already claimed? */
|
||||
if (0 != ep->driver_data)
|
||||
return 0;
|
||||
|
||||
|
||||
/* only support ep0 for portable CONTROL traffic */
|
||||
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
|
||||
if (USB_ENDPOINT_XFER_CONTROL == type)
|
||||
@@ -186,7 +186,7 @@ ep_matches (
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct usb_ep * __init
|
||||
static struct usb_ep * __devinit
|
||||
find_ep (struct usb_gadget *gadget, const char *name)
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
@@ -228,7 +228,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
|
||||
*
|
||||
* On failure, this returns a null endpoint descriptor.
|
||||
*/
|
||||
struct usb_ep * __init usb_ep_autoconfig (
|
||||
struct usb_ep * __devinit usb_ep_autoconfig (
|
||||
struct usb_gadget *gadget,
|
||||
struct usb_endpoint_descriptor *desc
|
||||
)
|
||||
@@ -276,7 +276,7 @@ struct usb_ep * __init usb_ep_autoconfig (
|
||||
return ep;
|
||||
}
|
||||
|
||||
/* Second, look at endpoints until an unclaimed one looks usable */
|
||||
/* Second, look at endpoints until an unclaimed one looks usable */
|
||||
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
|
||||
if (ep_matches (gadget, ep, desc))
|
||||
return ep;
|
||||
@@ -295,7 +295,7 @@ struct usb_ep * __init usb_ep_autoconfig (
|
||||
* state such as ep->driver_data and the record of assigned endpoints
|
||||
* used by usb_ep_autoconfig().
|
||||
*/
|
||||
void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
|
||||
void __devinit usb_ep_autoconfig_reset (struct usb_gadget *gadget)
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
|
||||
|
||||
@@ -2131,7 +2131,7 @@ eth_req_free (struct usb_ep *ep, struct usb_request *req)
|
||||
}
|
||||
|
||||
|
||||
static void __exit
|
||||
static void /* __init_or_exit */
|
||||
eth_unbind (struct usb_gadget *gadget)
|
||||
{
|
||||
struct eth_dev *dev = get_gadget_data (gadget);
|
||||
@@ -2158,7 +2158,7 @@ eth_unbind (struct usb_gadget *gadget)
|
||||
set_gadget_data (gadget, NULL);
|
||||
}
|
||||
|
||||
static u8 __init nibble (unsigned char c)
|
||||
static u8 __devinit nibble (unsigned char c)
|
||||
{
|
||||
if (likely (isdigit (c)))
|
||||
return c - '0';
|
||||
@@ -2168,7 +2168,7 @@ static u8 __init nibble (unsigned char c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init get_ether_addr(const char *str, u8 *dev_addr)
|
||||
static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
|
||||
{
|
||||
if (str) {
|
||||
unsigned i;
|
||||
@@ -2189,7 +2189,7 @@ static int __init get_ether_addr(const char *str, u8 *dev_addr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init
|
||||
static int __devinit
|
||||
eth_bind (struct usb_gadget *gadget)
|
||||
{
|
||||
struct eth_dev *dev;
|
||||
|
||||
@@ -3691,7 +3691,7 @@ static void lun_release(struct device *dev)
|
||||
kref_put(&fsg->ref, fsg_release);
|
||||
}
|
||||
|
||||
static void __exit fsg_unbind(struct usb_gadget *gadget)
|
||||
static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
|
||||
{
|
||||
struct fsg_dev *fsg = get_gadget_data(gadget);
|
||||
int i;
|
||||
|
||||
@@ -1398,7 +1398,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
|
||||
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
|
||||
|
||||
|
||||
int __init rndis_init (void)
|
||||
int __devinit rndis_init (void)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ int rndis_signal_disconnect (int configNr);
|
||||
int rndis_state (int configNr);
|
||||
extern void rndis_set_host_mac (int configNr, const u8 *addr);
|
||||
|
||||
int __init rndis_init (void);
|
||||
int __devinit rndis_init (void);
|
||||
void rndis_exit (void);
|
||||
|
||||
#endif /* _LINUX_RNDIS_H */
|
||||
|
||||
@@ -1473,7 +1473,7 @@ autoconf_fail:
|
||||
* Called on module unload. Frees the control request and device
|
||||
* structure.
|
||||
*/
|
||||
static void __exit gs_unbind(struct usb_gadget *gadget)
|
||||
static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
|
||||
{
|
||||
struct gs_dev *dev = get_gadget_data(gadget);
|
||||
|
||||
|
||||
@@ -1121,7 +1121,7 @@ zero_autoresume (unsigned long _dev)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void __exit
|
||||
static void /* __init_or_exit */
|
||||
zero_unbind (struct usb_gadget *gadget)
|
||||
{
|
||||
struct zero_dev *dev = get_gadget_data (gadget);
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
#endif
|
||||
#define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
|
||||
|
||||
#endif /* Au1200 */
|
||||
|
||||
extern int usb_disabled(void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -107,9 +105,9 @@ int usb_ehci_au1xxx_probe(const struct hc_driver *driver,
|
||||
|
||||
/* Au1200 AB USB does not support coherent memory */
|
||||
if (!(read_c0_prid() & 0xff)) {
|
||||
pr_info("%s: this is chip revision AB!\n", dev->dev.name);
|
||||
pr_info("%s: this is chip revision AB!\n", dev->name);
|
||||
pr_info("%s: update your board or re-configure the kernel\n",
|
||||
dev->dev.name);
|
||||
dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
@@ -228,9 +226,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ehci_hcd_au1xxx_drv_probe(struct device *dev)
|
||||
static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct usb_hcd *hcd = NULL;
|
||||
int ret;
|
||||
|
||||
@@ -243,10 +240,9 @@ static int ehci_hcd_au1xxx_drv_probe(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ehci_hcd_au1xxx_drv_remove(struct device *dev)
|
||||
static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
|
||||
usb_ehci_au1xxx_remove(hcd, pdev);
|
||||
return 0;
|
||||
@@ -269,12 +265,13 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
|
||||
}
|
||||
*/
|
||||
MODULE_ALIAS("au1xxx-ehci");
|
||||
/* FIXME use "struct platform_driver" */
|
||||
static struct device_driver ehci_hcd_au1xxx_driver = {
|
||||
.name = "au1xxx-ehci",
|
||||
.bus = &platform_bus_type,
|
||||
static struct platform_driver ehci_hcd_au1xxx_driver = {
|
||||
.probe = ehci_hcd_au1xxx_drv_probe,
|
||||
.remove = ehci_hcd_au1xxx_drv_remove,
|
||||
/*.suspend = ehci_hcd_au1xxx_drv_suspend, */
|
||||
/*.resume = ehci_hcd_au1xxx_drv_resume, */
|
||||
.driver = {
|
||||
.name = "au1xxx-ehci",
|
||||
.bus = &platform_bus_type
|
||||
}
|
||||
};
|
||||
|
||||
@@ -625,10 +625,11 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
|
||||
writel (status | CMD_RUN, &ehci->regs->command);
|
||||
|
||||
while (i--) {
|
||||
status = readl (&ehci->regs->port_status [i]);
|
||||
if (status & PORT_OWNER)
|
||||
int pstatus = readl (&ehci->regs->port_status [i]);
|
||||
|
||||
if (pstatus & PORT_OWNER)
|
||||
continue;
|
||||
if (!(status & PORT_RESUME)
|
||||
if (!(pstatus & PORT_RESUME)
|
||||
|| ehci->reset_done [i] != 0)
|
||||
continue;
|
||||
|
||||
@@ -891,7 +892,7 @@ MODULE_LICENSE ("GPL");
|
||||
#define PCI_DRIVER ehci_pci_driver
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_83xx
|
||||
#ifdef CONFIG_MPC834x
|
||||
#include "ehci-fsl.c"
|
||||
#define PLATFORM_DRIVER ehci_fsl_driver
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2004 SAN People (Pty) Ltd.
|
||||
* Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
|
||||
*
|
||||
* AT91RM9200 Bus Glue
|
||||
* AT91 Bus Glue
|
||||
*
|
||||
* Based on fragments of 2.4 driver by Rick Bronson.
|
||||
* Based on ohci-omap.c
|
||||
@@ -19,12 +19,13 @@
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/board.h>
|
||||
|
||||
#ifndef CONFIG_ARCH_AT91RM9200
|
||||
#error "CONFIG_ARCH_AT91RM9200 must be defined."
|
||||
#ifndef CONFIG_ARCH_AT91
|
||||
#error "CONFIG_ARCH_AT91 must be defined."
|
||||
#endif
|
||||
|
||||
/* interface and function clocks */
|
||||
static struct clk *iclk, *fclk;
|
||||
static int clocked;
|
||||
|
||||
extern int usb_disabled(void);
|
||||
|
||||
@@ -35,13 +36,14 @@ static void at91_start_hc(struct platform_device *pdev)
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct ohci_regs __iomem *regs = hcd->regs;
|
||||
|
||||
dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n");
|
||||
dev_dbg(&pdev->dev, "start\n");
|
||||
|
||||
/*
|
||||
* Start the USB clocks.
|
||||
*/
|
||||
clk_enable(iclk);
|
||||
clk_enable(fclk);
|
||||
clocked = 1;
|
||||
|
||||
/*
|
||||
* The USB host controller must remain in reset.
|
||||
@@ -54,7 +56,7 @@ static void at91_stop_hc(struct platform_device *pdev)
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct ohci_regs __iomem *regs = hcd->regs;
|
||||
|
||||
dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n");
|
||||
dev_dbg(&pdev->dev, "stop\n");
|
||||
|
||||
/*
|
||||
* Put the USB host controller into reset.
|
||||
@@ -66,6 +68,7 @@ static void at91_stop_hc(struct platform_device *pdev)
|
||||
*/
|
||||
clk_disable(fclk);
|
||||
clk_disable(iclk);
|
||||
clocked = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,14 +81,15 @@ static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
|
||||
|
||||
|
||||
/**
|
||||
* usb_hcd_at91_probe - initialize AT91RM9200-based HCDs
|
||||
* usb_hcd_at91_probe - initialize AT91-based HCDs
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* Allocates basic resources for this USB host controller, and
|
||||
* then invokes the start() method for the HCD associated with it
|
||||
* through the hotplug entry's driver_data.
|
||||
*/
|
||||
int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev)
|
||||
static int usb_hcd_at91_probe(const struct hc_driver *driver,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
int retval;
|
||||
struct usb_hcd *hcd = NULL;
|
||||
@@ -95,12 +99,13 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
|
||||
if ((pdev->resource[0].flags != IORESOURCE_MEM)
|
||||
|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
|
||||
pr_debug("hcd probe: invalid resource type\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200");
|
||||
hcd = usb_create_hcd(driver, &pdev->dev, "at91");
|
||||
if (!hcd)
|
||||
return -ENOMEM;
|
||||
hcd->rsrc_start = pdev->resource[0].start;
|
||||
@@ -149,21 +154,23 @@ int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *
|
||||
/* may be called with controller, bus, and devices active */
|
||||
|
||||
/**
|
||||
* usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs
|
||||
* usb_hcd_at91_remove - shutdown processing for AT91-based HCDs
|
||||
* @dev: USB Host Controller being removed
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* Reverses the effect of usb_hcd_at91_probe(), first invoking
|
||||
* the HCD's stop() method. It is always called from a thread
|
||||
* context, normally "rmmod", "apmd", or something similar.
|
||||
* context, "rmmod" or something similar.
|
||||
*
|
||||
*/
|
||||
static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev)
|
||||
static int usb_hcd_at91_remove(struct usb_hcd *hcd,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
usb_remove_hcd(hcd);
|
||||
at91_stop_hc(pdev);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
disable_irq_wake(hcd->irq);
|
||||
|
||||
clk_put(fclk);
|
||||
clk_put(iclk);
|
||||
@@ -178,19 +185,21 @@ static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pde
|
||||
static int __devinit
|
||||
ohci_at91_start (struct usb_hcd *hcd)
|
||||
{
|
||||
// struct at91_ohci_data *board = hcd->self.controller->platform_data;
|
||||
struct at91_usbh_data *board = hcd->self.controller->platform_data;
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
struct usb_device *root = hcd->self.root_hub;
|
||||
int ret;
|
||||
|
||||
if ((ret = ohci_init(ohci)) < 0)
|
||||
return ret;
|
||||
|
||||
root->maxchild = board->ports;
|
||||
|
||||
if ((ret = ohci_run(ohci)) < 0) {
|
||||
err("can't start %s", hcd->self.bus_name);
|
||||
ohci_stop(hcd);
|
||||
return ret;
|
||||
}
|
||||
// hcd->self.root_hub->maxchild = board->ports;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -198,7 +207,7 @@ ohci_at91_start (struct usb_hcd *hcd)
|
||||
|
||||
static const struct hc_driver ohci_at91_hc_driver = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "AT91RM9200 OHCI",
|
||||
.product_desc = "AT91 OHCI",
|
||||
.hcd_priv_size = sizeof(struct ohci_hcd),
|
||||
|
||||
/*
|
||||
@@ -240,33 +249,54 @@ static const struct hc_driver ohci_at91_hc_driver = {
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_hcd_at91_drv_probe(struct platform_device *dev)
|
||||
static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev);
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
|
||||
}
|
||||
|
||||
static int ohci_hcd_at91_drv_remove(struct platform_device *dev)
|
||||
static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
return usb_hcd_at91_remove(platform_get_drvdata(dev), dev);
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/* REVISIT suspend/resume look "too" simple here */
|
||||
|
||||
static int
|
||||
ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg)
|
||||
ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)
|
||||
{
|
||||
clk_disable(fclk);
|
||||
clk_disable(iclk);
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
enable_irq_wake(hcd->irq);
|
||||
else
|
||||
disable_irq_wake(hcd->irq);
|
||||
|
||||
/*
|
||||
* The integrated transceivers seem unable to notice disconnect,
|
||||
* reconnect, or wakeup without the 48 MHz clock active. so for
|
||||
* correctness, always discard connection state (using reset).
|
||||
*
|
||||
* REVISIT: some boards will be able to turn VBUS off...
|
||||
*/
|
||||
if (at91_suspend_entering_slow_clock()) {
|
||||
ohci_usb_reset (ohci);
|
||||
clk_disable(fclk);
|
||||
clk_disable(iclk);
|
||||
clocked = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ohci_hcd_at91_drv_resume(struct platform_device *dev)
|
||||
static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
|
||||
{
|
||||
clk_enable(iclk);
|
||||
clk_enable(fclk);
|
||||
if (!clocked) {
|
||||
clk_enable(iclk);
|
||||
clk_enable(fclk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -275,7 +305,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *dev)
|
||||
#define ohci_hcd_at91_drv_resume NULL
|
||||
#endif
|
||||
|
||||
MODULE_ALIAS("at91rm9200-ohci");
|
||||
MODULE_ALIAS("at91_ohci");
|
||||
|
||||
static struct platform_driver ohci_hcd_at91_driver = {
|
||||
.probe = ohci_hcd_at91_drv_probe,
|
||||
@@ -283,7 +313,7 @@ static struct platform_driver ohci_hcd_at91_driver = {
|
||||
.suspend = ohci_hcd_at91_drv_suspend,
|
||||
.resume = ohci_hcd_at91_drv_resume,
|
||||
.driver = {
|
||||
.name = "at91rm9200-ohci",
|
||||
.name = "at91_ohci",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -101,13 +101,16 @@ static void au1xxx_start_ohc(struct platform_device *dev)
|
||||
|
||||
#endif /* Au1200 */
|
||||
|
||||
#ifndef CONFIG_SOC_AU1200
|
||||
/* wait for reset complete (read register twice; see au1500 errata) */
|
||||
while (au_readl(USB_HOST_CONFIG),
|
||||
!(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
|
||||
#endif
|
||||
udelay(1000);
|
||||
|
||||
printk(KERN_DEBUG __FILE__
|
||||
": Clock to USB host has been enabled \n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void au1xxx_stop_ohc(struct platform_device *dev)
|
||||
@@ -157,9 +160,9 @@ static int usb_ohci_au1xxx_probe(const struct hc_driver *driver,
|
||||
/* Au1200 AB USB does not support coherent memory */
|
||||
if (!(read_c0_prid() & 0xff)) {
|
||||
pr_info("%s: this is chip revision AB !!\n",
|
||||
dev->dev.name);
|
||||
dev->name);
|
||||
pr_info("%s: update your board or re-configure the kernel\n",
|
||||
dev->dev.name);
|
||||
dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
225
drivers/usb/host/ohci-ep93xx.c
Normal file
225
drivers/usb/host/ohci-ep93xx.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
* (C) Copyright 2002 Hewlett-Packard Company
|
||||
*
|
||||
* Bus Glue for ep93xx.
|
||||
*
|
||||
* Written by Christopher Hoover <ch@hpl.hp.com>
|
||||
* Based on fragments of previous driver by Russell King et al.
|
||||
*
|
||||
* Modified for LH7A404 from ohci-sa1111.c
|
||||
* by Durgesh Pattamatta <pattamattad@sharpsec.com>
|
||||
*
|
||||
* Modified for pxa27x from ohci-lh7a404.c
|
||||
* by Nick Bane <nick@cecomputing.co.uk> 26-8-2004
|
||||
*
|
||||
* Modified for ep93xx from ohci-pxa27x.c
|
||||
* by Lennert Buytenhek <buytenh@wantstofly.org> 28-2-2006
|
||||
* Based on an earlier driver by Ray Lehtiniemi
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
static struct clk *usb_host_clock;
|
||||
|
||||
static void ep93xx_start_hc(struct device *dev)
|
||||
{
|
||||
clk_enable(usb_host_clock);
|
||||
}
|
||||
|
||||
static void ep93xx_stop_hc(struct device *dev)
|
||||
{
|
||||
clk_disable(usb_host_clock);
|
||||
}
|
||||
|
||||
static int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
int retval;
|
||||
struct usb_hcd *hcd;
|
||||
|
||||
if (pdev->resource[1].flags != IORESOURCE_IRQ) {
|
||||
pr_debug("resource[1] is not IORESOURCE_IRQ");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx");
|
||||
if (hcd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
hcd->rsrc_start = pdev->resource[0].start;
|
||||
hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
usb_put_hcd(hcd);
|
||||
retval = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
if (hcd->regs == NULL) {
|
||||
pr_debug("ioremap failed");
|
||||
retval = -ENOMEM;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
usb_host_clock = clk_get(&pdev->dev, "usb_host");
|
||||
ep93xx_start_hc(&pdev->dev);
|
||||
|
||||
ohci_hcd_init(hcd_to_ohci(hcd));
|
||||
|
||||
retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
|
||||
if (retval == 0)
|
||||
return retval;
|
||||
|
||||
ep93xx_stop_hc(&pdev->dev);
|
||||
iounmap(hcd->regs);
|
||||
err2:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
err1:
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
usb_remove_hcd(hcd);
|
||||
ep93xx_stop_hc(&pdev->dev);
|
||||
clk_put(usb_host_clock);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
usb_put_hcd(hcd);
|
||||
}
|
||||
|
||||
static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
int ret;
|
||||
|
||||
if ((ret = ohci_init(ohci)) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = ohci_run(ohci)) < 0) {
|
||||
err("can't start %s", hcd->self.bus_name);
|
||||
ohci_stop(hcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hc_driver ohci_ep93xx_hc_driver = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "EP93xx OHCI",
|
||||
.hcd_priv_size = sizeof(struct ohci_hcd),
|
||||
.irq = ohci_irq,
|
||||
.flags = HCD_USB11 | HCD_MEMORY,
|
||||
.start = ohci_ep93xx_start,
|
||||
.stop = ohci_stop,
|
||||
.urb_enqueue = ohci_urb_enqueue,
|
||||
.urb_dequeue = ohci_urb_dequeue,
|
||||
.endpoint_disable = ohci_endpoint_disable,
|
||||
.get_frame_number = ohci_get_frame,
|
||||
.hub_status_data = ohci_hub_status_data,
|
||||
.hub_control = ohci_hub_control,
|
||||
#ifdef CONFIG_PM
|
||||
.bus_suspend = ohci_bus_suspend,
|
||||
.bus_resume = ohci_bus_resume,
|
||||
#endif
|
||||
.start_port_reset = ohci_start_port_reset,
|
||||
};
|
||||
|
||||
extern int usb_disabled(void);
|
||||
|
||||
static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = -ENODEV;
|
||||
if (!usb_disabled())
|
||||
ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
|
||||
usb_hcd_ep93xx_remove(hcd, pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct ochi_hcd *ohci = hcd_to_ohci(hcd);
|
||||
|
||||
if (time_before(jiffies, ohci->next_statechange))
|
||||
msleep(5);
|
||||
ohci->next_statechange = jiffies;
|
||||
|
||||
ep93xx_stop_hc(&pdev->dev);
|
||||
hcd->state = HC_STATE_SUSPENDED;
|
||||
pdev->dev.power.power_state = PMSG_SUSPEND;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
int status;
|
||||
|
||||
if (time_before(jiffies, ohci->next_statechange))
|
||||
msleep(5);
|
||||
ohci->next_statechange = jiffies;
|
||||
|
||||
ep93xx_start_hc(&pdev->dev);
|
||||
pdev->dev.power.power_state = PMSG_ON;
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static struct platform_driver ohci_hcd_ep93xx_driver = {
|
||||
.probe = ohci_hcd_ep93xx_drv_probe,
|
||||
.remove = ohci_hcd_ep93xx_drv_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ohci_hcd_ep93xx_drv_suspend,
|
||||
.resume = ohci_hcd_ep93xx_drv_resume,
|
||||
#endif
|
||||
.driver = {
|
||||
.name = "ep93xx-ohci",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ohci_hcd_ep93xx_init(void)
|
||||
{
|
||||
return platform_driver_register(&ohci_hcd_ep93xx_driver);
|
||||
}
|
||||
|
||||
static void __exit ohci_hcd_ep93xx_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&ohci_hcd_ep93xx_driver);
|
||||
}
|
||||
|
||||
module_init(ohci_hcd_ep93xx_init);
|
||||
module_exit(ohci_hcd_ep93xx_cleanup);
|
||||
@@ -901,6 +901,10 @@ MODULE_LICENSE ("GPL");
|
||||
#include "ohci-pxa27x.c"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_EP93XX
|
||||
#include "ohci-ep93xx.c"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_AU1X00
|
||||
#include "ohci-au1xxx.c"
|
||||
#endif
|
||||
@@ -909,7 +913,7 @@ MODULE_LICENSE ("GPL");
|
||||
#include "ohci-ppc-soc.c"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_AT91RM9200
|
||||
#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261)
|
||||
#include "ohci-at91.c"
|
||||
#endif
|
||||
|
||||
@@ -919,9 +923,11 @@ MODULE_LICENSE ("GPL");
|
||||
|| defined(CONFIG_ARCH_OMAP) \
|
||||
|| defined (CONFIG_ARCH_LH7A404) \
|
||||
|| defined (CONFIG_PXA27x) \
|
||||
|| defined (CONFIG_ARCH_EP93XX) \
|
||||
|| defined (CONFIG_SOC_AU1X00) \
|
||||
|| defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
|
||||
|| defined (CONFIG_ARCH_AT91RM9200) \
|
||||
|| defined (CONFIG_ARCH_AT91SAM9261) \
|
||||
)
|
||||
#error "missing bus glue for ohci-hcd"
|
||||
#endif
|
||||
|
||||
@@ -581,14 +581,14 @@ static int ohci_hub_control (
|
||||
break;
|
||||
case GetHubStatus:
|
||||
temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
|
||||
*(__le32 *) buf = cpu_to_le32 (temp);
|
||||
put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
|
||||
break;
|
||||
case GetPortStatus:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
temp = roothub_portstatus (ohci, wIndex);
|
||||
*(__le32 *) buf = cpu_to_le32 (temp);
|
||||
put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
|
||||
|
||||
#ifndef OHCI_VERBOSE_DEBUG
|
||||
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
|
||||
|
||||
@@ -167,8 +167,6 @@ static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
|
||||
static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
||||
{
|
||||
void __iomem *base;
|
||||
int wait_time;
|
||||
u32 control;
|
||||
|
||||
if (!mmio_resource_enabled(pdev, 0))
|
||||
return;
|
||||
@@ -179,9 +177,10 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
||||
|
||||
/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
|
||||
#ifndef __hppa__
|
||||
control = readl(base + OHCI_CONTROL);
|
||||
{
|
||||
u32 control = readl(base + OHCI_CONTROL);
|
||||
if (control & OHCI_CTRL_IR) {
|
||||
wait_time = 500; /* arbitrary; 5 seconds */
|
||||
int wait_time = 500; /* arbitrary; 5 seconds */
|
||||
writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
|
||||
writel(OHCI_OCR, base + OHCI_CMDSTATUS);
|
||||
while (wait_time > 0 &&
|
||||
@@ -198,6 +197,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
||||
/* reset controller, preserving RWC */
|
||||
writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -943,7 +943,9 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
|
||||
/* We received a short packet */
|
||||
if (urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||
ret = -EREMOTEIO;
|
||||
else if (ctrlstat & TD_CTRL_SPD)
|
||||
|
||||
/* Fixup needed only if this isn't the URB's last TD */
|
||||
else if (&td->list != urbp->td_list.prev)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,9 +152,8 @@ static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
|
||||
* events. The hardware generates 5 events for the first keypress
|
||||
* and we have to take this into account for an accurate repeat
|
||||
* behaviour.
|
||||
* (HZ / 20) == 50 ms and works well for me.
|
||||
*/
|
||||
#define FILTER_TIME (HZ / 20)
|
||||
#define FILTER_TIME 60 /* msec */
|
||||
|
||||
struct ati_remote {
|
||||
struct input_dev *idev;
|
||||
@@ -467,7 +466,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
|
||||
/* Filter duplicate events which happen "too close" together. */
|
||||
if ((ati_remote->old_data[0] == data[1]) &&
|
||||
(ati_remote->old_data[1] == data[2]) &&
|
||||
time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) {
|
||||
time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(FILTER_TIME))) {
|
||||
ati_remote->repeat_count++;
|
||||
} else {
|
||||
ati_remote->repeat_count = 0;
|
||||
|
||||
@@ -1507,6 +1507,9 @@ void hid_init_reports(struct hid_device *hid)
|
||||
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
|
||||
#define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866
|
||||
|
||||
#define USB_VENDOR_ID_WISEGROUP_LTD 0x6677
|
||||
#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
|
||||
|
||||
#define USB_VENDOR_ID_CODEMERCS 0x07c0
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501
|
||||
@@ -1670,6 +1673,7 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
|
||||
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
|
||||
|
||||
@@ -88,19 +88,19 @@ config USB_LED
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called usbled.
|
||||
|
||||
config USB_CY7C63
|
||||
config USB_CYPRESS_CY7C63
|
||||
tristate "Cypress CY7C63xxx USB driver support"
|
||||
depends on USB
|
||||
help
|
||||
Say Y here if you want to connect a Cypress CY7C63xxx
|
||||
micro controller to your computer's USB port. This driver
|
||||
supports the pre-programmed devices (incl. firmware) by
|
||||
AK Modul-Bus Computer GmbH.
|
||||
micro controller to your computer's USB port. Currently this
|
||||
driver supports the pre-programmed devices (incl. firmware)
|
||||
by AK Modul-Bus Computer GmbH.
|
||||
|
||||
Please see: http://www.ak-modul-bus.de/stat/mikrocontroller.html
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cy7c63.
|
||||
module will be called cypress_cy7c63.
|
||||
|
||||
config USB_CYTHERM
|
||||
tristate "Cypress USB thermometer driver support"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
|
||||
obj-$(CONFIG_USB_CY7C63) += cy7c63.o
|
||||
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
|
||||
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
|
||||
obj-$(CONFIG_USB_EMI26) += emi26.o
|
||||
obj-$(CONFIG_USB_EMI62) += emi62.o
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
* cy7c63.c
|
||||
*
|
||||
* Copyright (c) 2006 Oliver Bock (bock@fh-wolfenbuettel.de)
|
||||
*
|
||||
* This driver is based on the Cypress Thermometer USB Driver by
|
||||
* Marcus Maul and the 2.0 version of Greg Kroah-Hartman's
|
||||
* USB Skeleton driver.
|
||||
*
|
||||
* Is is a generic driver for the Cypress CY7C63000 family.
|
||||
* For the time being it enables you to toggle the single I/O ports
|
||||
* of the device.
|
||||
*
|
||||
* Supported vendors: AK Modul-Bus Computer GmbH
|
||||
* Supported devices: CY7C63001A-PC (to be continued...)
|
||||
* Supported functions: Read/Write Ports (to be continued...)
|
||||
*
|
||||
* Chipsets families: CY7C63000, CY7C63001, CY7C63100, CY7C63101
|
||||
*
|
||||
*
|
||||
* 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, version 2.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#define DRIVER_AUTHOR "Oliver Bock (bock@fh-wolfenbuettel.de)"
|
||||
#define DRIVER_DESC "Cypress CY7C63xxx USB driver"
|
||||
|
||||
#define CY7C63_VENDOR_ID 0xa2c
|
||||
#define CY7C63_PRODUCT_ID 0x8
|
||||
|
||||
#define CY7C63_READ_PORT 0x4
|
||||
#define CY7C63_WRITE_PORT 0x5
|
||||
#define CY7C63_READ_RAM 0x2
|
||||
#define CY7C63_WRITE_RAM 0x3
|
||||
#define CY7C63_READ_ROM 0x1
|
||||
|
||||
#define CY7C63_READ_PORT_ID0 0
|
||||
#define CY7C63_WRITE_PORT_ID0 0
|
||||
#define CY7C63_READ_PORT_ID1 0x2
|
||||
#define CY7C63_WRITE_PORT_ID1 1
|
||||
|
||||
#define CY7C63_MAX_REQSIZE 8
|
||||
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static struct usb_device_id cy7c63_table [] = {
|
||||
{ USB_DEVICE(CY7C63_VENDOR_ID, CY7C63_PRODUCT_ID) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, cy7c63_table);
|
||||
|
||||
/* structure to hold all of our device specific stuff */
|
||||
struct cy7c63 {
|
||||
struct usb_device * udev;
|
||||
char port0;
|
||||
char port1;
|
||||
};
|
||||
|
||||
/* used to send usb control messages to device */
|
||||
int vendor_command(struct cy7c63 *dev, unsigned char request,
|
||||
unsigned char address, unsigned char data) {
|
||||
|
||||
int retval = 0;
|
||||
unsigned int pipe;
|
||||
unsigned char *iobuf;
|
||||
|
||||
/* allocate some memory for the i/o buffer*/
|
||||
iobuf = kzalloc(CY7C63_MAX_REQSIZE, GFP_KERNEL);
|
||||
if (!iobuf) {
|
||||
dev_err(&dev->udev->dev, "Out of memory!\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data);
|
||||
|
||||
/* prepare usb control message and send it upstream */
|
||||
pipe = usb_rcvctrlpipe(dev->udev, 0);
|
||||
retval = usb_control_msg(dev->udev, pipe, request,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
|
||||
address, data, iobuf, CY7C63_MAX_REQSIZE,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
|
||||
/* store returned data (more READs to be added!) */
|
||||
switch (request) {
|
||||
case CY7C63_READ_PORT:
|
||||
if (address == CY7C63_READ_PORT_ID0) {
|
||||
dev->port0 = iobuf[1];
|
||||
dev_dbg(&dev->udev->dev,
|
||||
"READ_PORT0 returned: %d\n",dev->port0);
|
||||
}
|
||||
else if (address == CY7C63_READ_PORT_ID1) {
|
||||
dev->port1 = iobuf[1];
|
||||
dev_dbg(&dev->udev->dev,
|
||||
"READ_PORT1 returned: %d\n",dev->port1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(iobuf);
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define get_set_port(num,read_id,write_id) \
|
||||
static ssize_t set_port##num(struct device *dev, struct device_attribute *attr, \
|
||||
const char *buf, size_t count) { \
|
||||
\
|
||||
int value; \
|
||||
int result = 0; \
|
||||
\
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct cy7c63 *cyp = usb_get_intfdata(intf); \
|
||||
\
|
||||
dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", num); \
|
||||
\
|
||||
/* validate input data */ \
|
||||
if (sscanf(buf, "%d", &value) < 1) { \
|
||||
result = -EINVAL; \
|
||||
goto error; \
|
||||
} \
|
||||
if (value>255 || value<0) { \
|
||||
result = -EINVAL; \
|
||||
goto error; \
|
||||
} \
|
||||
\
|
||||
result = vendor_command(cyp, CY7C63_WRITE_PORT, write_id, \
|
||||
(unsigned char)value); \
|
||||
\
|
||||
dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n",result); \
|
||||
error: \
|
||||
return result < 0 ? result : count; \
|
||||
} \
|
||||
\
|
||||
static ssize_t get_port##num(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) { \
|
||||
\
|
||||
int result = 0; \
|
||||
\
|
||||
struct usb_interface *intf = to_usb_interface(dev); \
|
||||
struct cy7c63 *cyp = usb_get_intfdata(intf); \
|
||||
\
|
||||
dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", num); \
|
||||
\
|
||||
result = vendor_command(cyp, CY7C63_READ_PORT, read_id, 0); \
|
||||
\
|
||||
dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result); \
|
||||
\
|
||||
return sprintf(buf, "%d", cyp->port##num); \
|
||||
} \
|
||||
static DEVICE_ATTR(port##num, S_IWUGO | S_IRUGO, get_port##num, set_port##num);
|
||||
|
||||
get_set_port(0, CY7C63_READ_PORT_ID0, CY7C63_WRITE_PORT_ID0);
|
||||
get_set_port(1, CY7C63_READ_PORT_ID1, CY7C63_WRITE_PORT_ID1);
|
||||
|
||||
static int cy7c63_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *id) {
|
||||
|
||||
struct cy7c63 *dev = NULL;
|
||||
int retval = -ENOMEM;
|
||||
|
||||
/* allocate memory for our device state and initialize it */
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (dev == NULL) {
|
||||
dev_err(&dev->udev->dev, "Out of memory!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev->udev = usb_get_dev(interface_to_usbdev(interface));
|
||||
|
||||
/* save our data pointer in this interface device */
|
||||
usb_set_intfdata(interface, dev);
|
||||
|
||||
/* create device attribute files */
|
||||
device_create_file(&interface->dev, &dev_attr_port0);
|
||||
device_create_file(&interface->dev, &dev_attr_port1);
|
||||
|
||||
/* let the user know what node this device is now attached to */
|
||||
dev_info(&interface->dev,
|
||||
"Cypress CY7C63xxx device now attached\n");
|
||||
|
||||
retval = 0;
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void cy7c63_disconnect(struct usb_interface *interface) {
|
||||
|
||||
struct cy7c63 *dev;
|
||||
|
||||
dev = usb_get_intfdata(interface);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
|
||||
/* remove device attribute files */
|
||||
device_remove_file(&interface->dev, &dev_attr_port0);
|
||||
device_remove_file(&interface->dev, &dev_attr_port1);
|
||||
|
||||
usb_put_dev(dev->udev);
|
||||
|
||||
dev_info(&interface->dev,
|
||||
"Cypress CY7C63xxx device now disconnected\n");
|
||||
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
static struct usb_driver cy7c63_driver = {
|
||||
.name = "cy7c63",
|
||||
.probe = cy7c63_probe,
|
||||
.disconnect = cy7c63_disconnect,
|
||||
.id_table = cy7c63_table,
|
||||
};
|
||||
|
||||
static int __init cy7c63_init(void) {
|
||||
|
||||
int result;
|
||||
|
||||
/* register this driver with the USB subsystem */
|
||||
result = usb_register(&cy7c63_driver);
|
||||
if (result) {
|
||||
err("Function usb_register failed! Error number: %d\n", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit cy7c63_exit(void) {
|
||||
|
||||
/* deregister this driver with the USB subsystem */
|
||||
usb_deregister(&cy7c63_driver);
|
||||
}
|
||||
|
||||
module_init(cy7c63_init);
|
||||
module_exit(cy7c63_exit);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
284
drivers/usb/misc/cypress_cy7c63.c
Normal file
284
drivers/usb/misc/cypress_cy7c63.c
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* cypress_cy7c63.c
|
||||
*
|
||||
* Copyright (c) 2006 Oliver Bock (o.bock@fh-wolfenbuettel.de)
|
||||
*
|
||||
* This driver is based on the Cypress USB Driver by Marcus Maul
|
||||
* (cyport) and the 2.0 version of Greg Kroah-Hartman's
|
||||
* USB Skeleton driver.
|
||||
*
|
||||
* This is a generic driver for the Cypress CY7C63xxx family.
|
||||
* For the time being it enables you to read from and write to
|
||||
* the single I/O ports of the device.
|
||||
*
|
||||
* Supported vendors: AK Modul-Bus Computer GmbH
|
||||
* (Firmware "Port-Chip")
|
||||
*
|
||||
* Supported devices: CY7C63001A-PC
|
||||
* CY7C63001C-PXC
|
||||
* CY7C63001C-SXC
|
||||
*
|
||||
* Supported functions: Read/Write Ports
|
||||
*
|
||||
*
|
||||
* 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, version 2.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#define DRIVER_AUTHOR "Oliver Bock (o.bock@fh-wolfenbuettel.de)"
|
||||
#define DRIVER_DESC "Cypress CY7C63xxx USB driver"
|
||||
|
||||
#define CYPRESS_VENDOR_ID 0xa2c
|
||||
#define CYPRESS_PRODUCT_ID 0x8
|
||||
|
||||
#define CYPRESS_READ_PORT 0x4
|
||||
#define CYPRESS_WRITE_PORT 0x5
|
||||
|
||||
#define CYPRESS_READ_RAM 0x2
|
||||
#define CYPRESS_WRITE_RAM 0x3
|
||||
#define CYPRESS_READ_ROM 0x1
|
||||
|
||||
#define CYPRESS_READ_PORT_ID0 0
|
||||
#define CYPRESS_WRITE_PORT_ID0 0
|
||||
#define CYPRESS_READ_PORT_ID1 0x2
|
||||
#define CYPRESS_WRITE_PORT_ID1 1
|
||||
|
||||
#define CYPRESS_MAX_REQSIZE 8
|
||||
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static struct usb_device_id cypress_table [] = {
|
||||
{ USB_DEVICE(CYPRESS_VENDOR_ID, CYPRESS_PRODUCT_ID) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, cypress_table);
|
||||
|
||||
/* structure to hold all of our device specific stuff */
|
||||
struct cypress {
|
||||
struct usb_device * udev;
|
||||
unsigned char port[2];
|
||||
};
|
||||
|
||||
/* used to send usb control messages to device */
|
||||
static int vendor_command(struct cypress *dev, unsigned char request,
|
||||
unsigned char address, unsigned char data)
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned int pipe;
|
||||
unsigned char *iobuf;
|
||||
|
||||
/* allocate some memory for the i/o buffer*/
|
||||
iobuf = kzalloc(CYPRESS_MAX_REQSIZE, GFP_KERNEL);
|
||||
if (!iobuf) {
|
||||
dev_err(&dev->udev->dev, "Out of memory!\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data);
|
||||
|
||||
/* prepare usb control message and send it upstream */
|
||||
pipe = usb_rcvctrlpipe(dev->udev, 0);
|
||||
retval = usb_control_msg(dev->udev, pipe, request,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
|
||||
address, data, iobuf, CYPRESS_MAX_REQSIZE,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
|
||||
/* store returned data (more READs to be added) */
|
||||
switch (request) {
|
||||
case CYPRESS_READ_PORT:
|
||||
if (address == CYPRESS_READ_PORT_ID0) {
|
||||
dev->port[0] = iobuf[1];
|
||||
dev_dbg(&dev->udev->dev,
|
||||
"READ_PORT0 returned: %d\n",
|
||||
dev->port[0]);
|
||||
}
|
||||
else if (address == CYPRESS_READ_PORT_ID1) {
|
||||
dev->port[1] = iobuf[1];
|
||||
dev_dbg(&dev->udev->dev,
|
||||
"READ_PORT1 returned: %d\n",
|
||||
dev->port[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(iobuf);
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* write port value */
|
||||
static ssize_t write_port(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count,
|
||||
int port_num, int write_id)
|
||||
{
|
||||
int value = -1;
|
||||
int result = 0;
|
||||
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct cypress *cyp = usb_get_intfdata(intf);
|
||||
|
||||
dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", port_num);
|
||||
|
||||
/* validate input data */
|
||||
if (sscanf(buf, "%d", &value) < 1) {
|
||||
result = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (value < 0 || value > 255) {
|
||||
result = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = vendor_command(cyp, CYPRESS_WRITE_PORT, write_id,
|
||||
(unsigned char)value);
|
||||
|
||||
dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
|
||||
error:
|
||||
return result < 0 ? result : count;
|
||||
}
|
||||
|
||||
/* attribute callback handler (write) */
|
||||
static ssize_t set_port0_handler(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return write_port(dev, attr, buf, count, 0, CYPRESS_WRITE_PORT_ID0);
|
||||
}
|
||||
|
||||
/* attribute callback handler (write) */
|
||||
static ssize_t set_port1_handler(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return write_port(dev, attr, buf, count, 1, CYPRESS_WRITE_PORT_ID1);
|
||||
}
|
||||
|
||||
/* read port value */
|
||||
static ssize_t read_port(struct device *dev, struct device_attribute *attr,
|
||||
char *buf, int port_num, int read_id)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
struct usb_interface *intf = to_usb_interface(dev);
|
||||
struct cypress *cyp = usb_get_intfdata(intf);
|
||||
|
||||
dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", port_num);
|
||||
|
||||
result = vendor_command(cyp, CYPRESS_READ_PORT, read_id, 0);
|
||||
|
||||
dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
|
||||
|
||||
return sprintf(buf, "%d", cyp->port[port_num]);
|
||||
}
|
||||
|
||||
/* attribute callback handler (read) */
|
||||
static ssize_t get_port0_handler(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0);
|
||||
}
|
||||
|
||||
/* attribute callback handler (read) */
|
||||
static ssize_t get_port1_handler(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO,
|
||||
get_port0_handler, set_port0_handler);
|
||||
|
||||
static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO,
|
||||
get_port1_handler, set_port1_handler);
|
||||
|
||||
|
||||
static int cypress_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct cypress *dev = NULL;
|
||||
int retval = -ENOMEM;
|
||||
|
||||
/* allocate memory for our device state and initialize it */
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (dev == NULL) {
|
||||
dev_err(&dev->udev->dev, "Out of memory!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev->udev = usb_get_dev(interface_to_usbdev(interface));
|
||||
|
||||
/* save our data pointer in this interface device */
|
||||
usb_set_intfdata(interface, dev);
|
||||
|
||||
/* create device attribute files */
|
||||
device_create_file(&interface->dev, &dev_attr_port0);
|
||||
device_create_file(&interface->dev, &dev_attr_port1);
|
||||
|
||||
/* let the user know that the device is now attached */
|
||||
dev_info(&interface->dev,
|
||||
"Cypress CY7C63xxx device now attached\n");
|
||||
|
||||
retval = 0;
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void cypress_disconnect(struct usb_interface *interface)
|
||||
{
|
||||
struct cypress *dev;
|
||||
|
||||
dev = usb_get_intfdata(interface);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
|
||||
/* remove device attribute files */
|
||||
device_remove_file(&interface->dev, &dev_attr_port0);
|
||||
device_remove_file(&interface->dev, &dev_attr_port1);
|
||||
|
||||
usb_put_dev(dev->udev);
|
||||
|
||||
dev_info(&interface->dev,
|
||||
"Cypress CY7C63xxx device now disconnected\n");
|
||||
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
static struct usb_driver cypress_driver = {
|
||||
.name = "cypress_cy7c63",
|
||||
.probe = cypress_probe,
|
||||
.disconnect = cypress_disconnect,
|
||||
.id_table = cypress_table,
|
||||
};
|
||||
|
||||
static int __init cypress_init(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* register this driver with the USB subsystem */
|
||||
result = usb_register(&cypress_driver);
|
||||
if (result) {
|
||||
err("Function usb_register failed! Error number: %d\n", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void __exit cypress_exit(void)
|
||||
{
|
||||
/* deregister this driver with the USB subsystem */
|
||||
usb_deregister(&cypress_driver);
|
||||
}
|
||||
|
||||
module_init(cypress_init);
|
||||
module_exit(cypress_exit);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -200,10 +200,8 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
|
||||
|
||||
/* create a urb, and a buffer for it, and copy the data to the urb */
|
||||
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
|
||||
if (!buf) {
|
||||
|
||||
@@ -64,7 +64,6 @@ struct mon_reader_text {
|
||||
};
|
||||
|
||||
static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
|
||||
static void mon_text_dtor(void *, kmem_cache_t *, unsigned long);
|
||||
|
||||
/*
|
||||
* mon_text_submit
|
||||
@@ -268,7 +267,7 @@ static int mon_text_open(struct inode *inode, struct file *file)
|
||||
(long)rp);
|
||||
rp->e_slab = kmem_cache_create(rp->slab_name,
|
||||
sizeof(struct mon_event_text), sizeof(long), 0,
|
||||
mon_text_ctor, mon_text_dtor);
|
||||
mon_text_ctor, NULL);
|
||||
if (rp->e_slab == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto err_slab;
|
||||
@@ -459,7 +458,3 @@ static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags)
|
||||
memset(mem, 0xe5, sizeof(struct mon_event_text));
|
||||
}
|
||||
|
||||
static void mon_text_dtor(void *mem, kmem_cache_t *slab, unsigned long sflags)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
@@ -128,11 +128,13 @@
|
||||
#define VENDOR_ID_MELCO 0x0411
|
||||
#define VENDOR_ID_MICRONET 0x3980
|
||||
#define VENDOR_ID_LONGSHINE 0x07b8
|
||||
#define VENDOR_ID_ZYXEL 0x0586
|
||||
|
||||
#define PRODUCT_ID_RTL8150 0x8150
|
||||
#define PRODUCT_ID_LUAKTX 0x0012
|
||||
#define PRODUCT_ID_LCS8138TX 0x401a
|
||||
#define PRODUCT_ID_SP128AR 0x0003
|
||||
#define PRODUCT_ID_PRESTIGE 0x401a
|
||||
|
||||
#undef EEPROM_WRITE
|
||||
|
||||
@@ -142,6 +144,7 @@ static struct usb_device_id rtl8150_table[] = {
|
||||
{USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},
|
||||
{USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)},
|
||||
{USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)},
|
||||
{USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -172,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *);
|
||||
static void rtl8150_disconnect(struct usb_interface *intf);
|
||||
static int rtl8150_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id);
|
||||
static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message);
|
||||
static int rtl8150_resume(struct usb_interface *intf);
|
||||
|
||||
static const char driver_name [] = "rtl8150";
|
||||
|
||||
@@ -180,6 +185,8 @@ static struct usb_driver rtl8150_driver = {
|
||||
.probe = rtl8150_probe,
|
||||
.disconnect = rtl8150_disconnect,
|
||||
.id_table = rtl8150_table,
|
||||
.suspend = rtl8150_suspend,
|
||||
.resume = rtl8150_resume
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -235,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
|
||||
usb_fill_control_urb(dev->ctrl_urb, dev->udev,
|
||||
usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,
|
||||
&dev->rx_creg, size, ctrl_callback, dev);
|
||||
if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC)))
|
||||
if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) {
|
||||
if (ret == -ENODEV)
|
||||
netif_device_detach(dev->netdev);
|
||||
err("control request submission failed: %d", ret);
|
||||
else
|
||||
} else
|
||||
set_bit(RX_REG_SET, &dev->flags);
|
||||
|
||||
return ret;
|
||||
@@ -413,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
|
||||
struct sk_buff *skb;
|
||||
struct net_device *netdev;
|
||||
u16 rx_stat;
|
||||
int status;
|
||||
|
||||
dev = urb->context;
|
||||
if (!dev)
|
||||
@@ -462,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
|
||||
goon:
|
||||
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
|
||||
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
|
||||
if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
|
||||
status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
|
||||
if (status == -ENODEV)
|
||||
netif_device_detach(dev->netdev);
|
||||
else if (status) {
|
||||
set_bit(RX_URB_FAIL, &dev->flags);
|
||||
goto resched;
|
||||
} else {
|
||||
@@ -478,6 +491,7 @@ static void rx_fixup(unsigned long data)
|
||||
{
|
||||
rtl8150_t *dev;
|
||||
struct sk_buff *skb;
|
||||
int status;
|
||||
|
||||
dev = (rtl8150_t *)data;
|
||||
|
||||
@@ -496,10 +510,13 @@ static void rx_fixup(unsigned long data)
|
||||
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
|
||||
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
|
||||
try_again:
|
||||
if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
|
||||
status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
|
||||
if (status == -ENODEV) {
|
||||
netif_device_detach(dev->netdev);
|
||||
} else if (status) {
|
||||
set_bit(RX_URB_FAIL, &dev->flags);
|
||||
goto tlsched;
|
||||
} else {
|
||||
} else {
|
||||
clear_bit(RX_URB_FAIL, &dev->flags);
|
||||
}
|
||||
|
||||
@@ -571,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
|
||||
|
||||
resubmit:
|
||||
status = usb_submit_urb (urb, SLAB_ATOMIC);
|
||||
if (status)
|
||||
if (status == -ENODEV)
|
||||
netif_device_detach(dev->netdev);
|
||||
else if (status)
|
||||
err ("can't resubmit intr, %s-%s/input0, status %d",
|
||||
dev->udev->bus->bus_name,
|
||||
dev->udev->devpath, status);
|
||||
}
|
||||
|
||||
static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
{
|
||||
rtl8150_t *dev = usb_get_intfdata(intf);
|
||||
|
||||
netif_device_detach(dev->netdev);
|
||||
|
||||
if (netif_running(dev->netdev)) {
|
||||
usb_kill_urb(dev->rx_urb);
|
||||
usb_kill_urb(dev->intr_urb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8150_resume(struct usb_interface *intf)
|
||||
{
|
||||
rtl8150_t *dev = usb_get_intfdata(intf);
|
||||
|
||||
netif_device_attach(dev->netdev);
|
||||
if (netif_running(dev->netdev)) {
|
||||
dev->rx_urb->status = 0;
|
||||
dev->rx_urb->actual_length = 0;
|
||||
read_bulk_callback(dev->rx_urb, NULL);
|
||||
|
||||
dev->intr_urb->status = 0;
|
||||
dev->intr_urb->actual_length = 0;
|
||||
intr_callback(dev->intr_urb, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
@@ -687,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),
|
||||
skb->data, count, write_bulk_callback, dev);
|
||||
if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) {
|
||||
warn("failed tx_urb %d\n", res);
|
||||
dev->stats.tx_errors++;
|
||||
netif_start_queue(netdev);
|
||||
/* Can we get/handle EPIPE here? */
|
||||
if (res == -ENODEV)
|
||||
netif_device_detach(dev->netdev);
|
||||
else {
|
||||
warn("failed tx_urb %d\n", res);
|
||||
dev->stats.tx_errors++;
|
||||
netif_start_queue(netdev);
|
||||
}
|
||||
} else {
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
@@ -726,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev)
|
||||
|
||||
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
|
||||
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
|
||||
if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL)))
|
||||
if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) {
|
||||
if (res == -ENODEV)
|
||||
netif_device_detach(dev->netdev);
|
||||
warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
|
||||
return res;
|
||||
}
|
||||
usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),
|
||||
dev->intr_buff, INTBUFSIZE, intr_callback,
|
||||
dev, dev->intr_interval);
|
||||
if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL)))
|
||||
if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) {
|
||||
if (res == -ENODEV)
|
||||
netif_device_detach(dev->netdev);
|
||||
warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
|
||||
netif_start_queue(netdev);
|
||||
usb_kill_urb(dev->rx_urb);
|
||||
return res;
|
||||
}
|
||||
enable_net_traffic(dev);
|
||||
set_carrier(netdev);
|
||||
netif_start_queue(netdev);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -62,15 +62,6 @@ config USB_SERIAL_AIRPRIME
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called airprime.
|
||||
|
||||
config USB_SERIAL_ANYDATA
|
||||
tristate "USB AnyData CDMA Wireless Driver"
|
||||
depends on USB_SERIAL
|
||||
help
|
||||
Say Y here if you want to use a AnyData CDMA device.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called anydata.
|
||||
|
||||
config USB_SERIAL_ARK3116
|
||||
tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)"
|
||||
depends on USB_SERIAL && EXPERIMENTAL
|
||||
@@ -456,6 +447,17 @@ config USB_SERIAL_SAFE_PADDED
|
||||
bool "USB Secure Encapsulated Driver - Padded"
|
||||
depends on USB_SERIAL_SAFE
|
||||
|
||||
config USB_SERIAL_SIERRAWIRELESS
|
||||
tristate "USB Sierra Wireless Driver"
|
||||
depends on USB_SERIAL
|
||||
help
|
||||
Say M here if you want to use a Sierra Wireless device (if
|
||||
using an PC 5220 or AC580 please use the Airprime driver
|
||||
instead).
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sierra.
|
||||
|
||||
config USB_SERIAL_TI
|
||||
tristate "USB TI 3410/5052 Serial Driver"
|
||||
depends on USB_SERIAL
|
||||
@@ -491,15 +493,18 @@ config USB_SERIAL_XIRCOM
|
||||
module will be called keyspan_pda.
|
||||
|
||||
config USB_SERIAL_OPTION
|
||||
tristate "USB driver for GSM modems"
|
||||
tristate "USB driver for GSM and CDMA modems"
|
||||
depends on USB_SERIAL
|
||||
help
|
||||
Say Y here if you have an "Option" GSM PCMCIA card
|
||||
(or an OEM version: branded Huawei, Audiovox, or Novatel).
|
||||
Say Y here if you have a GSM or CDMA modem that's connected to USB.
|
||||
|
||||
These cards feature a built-in OHCI-USB adapter and an
|
||||
internally-connected GSM modem. The USB bus is not
|
||||
accessible externally.
|
||||
This driver also supports several PCMCIA cards which have a
|
||||
built-in OHCI-USB adapter and an internally-connected GSM modem.
|
||||
The USB bus on these cards is not accessible externally.
|
||||
|
||||
Supported devices include (some of?) those made by:
|
||||
Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or
|
||||
Anydata.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called option.
|
||||
|
||||
@@ -12,7 +12,6 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o
|
||||
usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
|
||||
|
||||
obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o
|
||||
obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o
|
||||
obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
|
||||
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
|
||||
obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
|
||||
@@ -39,6 +38,7 @@ obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
|
||||
obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
|
||||
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
|
||||
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
|
||||
obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
|
||||
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
|
||||
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
|
||||
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* AnyData CDMA Serial USB driver
|
||||
*
|
||||
* Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(0x16d5, 0x6501) }, /* AirData CDMA device */
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, id_table);
|
||||
|
||||
/* if overridden by the user, then use their value for the size of the
|
||||
* read and write urbs */
|
||||
static int buffer_size;
|
||||
static int debug;
|
||||
|
||||
static struct usb_driver anydata_driver = {
|
||||
.name = "anydata",
|
||||
.probe = usb_serial_probe,
|
||||
.disconnect = usb_serial_disconnect,
|
||||
.id_table = id_table,
|
||||
.no_dynamic_id = 1,
|
||||
};
|
||||
|
||||
static int anydata_open(struct usb_serial_port *port, struct file *filp)
|
||||
{
|
||||
char *buffer;
|
||||
int result = 0;
|
||||
|
||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||
|
||||
if (buffer_size) {
|
||||
/* override the default buffer sizes */
|
||||
buffer = kmalloc(buffer_size, GFP_KERNEL);
|
||||
if (!buffer) {
|
||||
dev_err(&port->dev, "%s - out of memory.\n",
|
||||
__FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kfree (port->read_urb->transfer_buffer);
|
||||
port->read_urb->transfer_buffer = buffer;
|
||||
port->read_urb->transfer_buffer_length = buffer_size;
|
||||
|
||||
buffer = kmalloc(buffer_size, GFP_KERNEL);
|
||||
if (!buffer) {
|
||||
dev_err(&port->dev, "%s - out of memory.\n",
|
||||
__FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kfree (port->write_urb->transfer_buffer);
|
||||
port->write_urb->transfer_buffer = buffer;
|
||||
port->write_urb->transfer_buffer_length = buffer_size;
|
||||
port->bulk_out_size = buffer_size;
|
||||
}
|
||||
|
||||
/* Start reading from the device */
|
||||
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
|
||||
usb_rcvbulkpipe(port->serial->dev,
|
||||
port->bulk_in_endpointAddress),
|
||||
port->read_urb->transfer_buffer,
|
||||
port->read_urb->transfer_buffer_length,
|
||||
usb_serial_generic_write_bulk_callback, port);
|
||||
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
||||
if (result)
|
||||
dev_err(&port->dev,
|
||||
"%s - failed submitting read urb, error %d\n",
|
||||
__FUNCTION__, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct usb_serial_driver anydata_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "anydata",
|
||||
},
|
||||
.id_table = id_table,
|
||||
.num_interrupt_in = NUM_DONT_CARE,
|
||||
.num_bulk_in = NUM_DONT_CARE,
|
||||
.num_bulk_out = NUM_DONT_CARE,
|
||||
.num_ports = 1,
|
||||
.open = anydata_open,
|
||||
};
|
||||
|
||||
static int __init anydata_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = usb_serial_register(&anydata_device);
|
||||
if (retval)
|
||||
return retval;
|
||||
retval = usb_register(&anydata_driver);
|
||||
if (retval)
|
||||
usb_serial_deregister(&anydata_device);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit anydata_exit(void)
|
||||
{
|
||||
usb_deregister(&anydata_driver);
|
||||
usb_serial_deregister(&anydata_device);
|
||||
}
|
||||
|
||||
module_init(anydata_init);
|
||||
module_exit(anydata_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||
module_param(buffer_size, int, 0);
|
||||
MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers");
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
|
||||
static int debug;
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "belkin_sa.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
#include "usb-serial.h"
|
||||
|
||||
struct usbcons_info {
|
||||
int magic;
|
||||
int break_flag;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/usb.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
#define CYBERJACK_LOCAL_BUF_SIZE 32
|
||||
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "usb-serial.h"
|
||||
#include "cypress_m8.h"
|
||||
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/wait.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
/* Defines */
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
|
||||
#define CPUCS_REG 0x7F92
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/serial.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "ftdi_sio.h"
|
||||
|
||||
/*
|
||||
@@ -313,6 +313,7 @@ static struct usb_device_id id_table_combined [] = {
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
|
||||
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
|
||||
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
|
||||
@@ -336,6 +337,7 @@ static struct usb_device_id id_table_combined [] = {
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
|
||||
@@ -500,6 +502,8 @@ static struct usb_device_id id_table_combined [] = {
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
|
||||
{ USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
|
||||
{ }, /* Optional parameter entry */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
@@ -548,11 +552,17 @@ struct ftdi_private {
|
||||
spinlock_t rx_lock; /* spinlock for receive state */
|
||||
struct work_struct rx_work;
|
||||
int rx_processed;
|
||||
unsigned long rx_bytes;
|
||||
|
||||
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
|
||||
|
||||
int force_baud; /* if non-zero, force the baud rate to this value */
|
||||
int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
|
||||
|
||||
spinlock_t tx_lock; /* spinlock for transmit state */
|
||||
unsigned long tx_bytes;
|
||||
unsigned long tx_outstanding_bytes;
|
||||
unsigned long tx_outstanding_urbs;
|
||||
};
|
||||
|
||||
/* Used for TIOCMIWAIT */
|
||||
@@ -626,6 +636,9 @@ static struct usb_serial_driver ftdi_sio_device = {
|
||||
#define HIGH 1
|
||||
#define LOW 0
|
||||
|
||||
/* number of outstanding urbs to prevent userspace DoS from happening */
|
||||
#define URB_UPPER_LIMIT 42
|
||||
|
||||
/*
|
||||
* ***************************************************************************
|
||||
* Utlity functions
|
||||
@@ -1156,6 +1169,7 @@ static int ftdi_sio_attach (struct usb_serial *serial)
|
||||
}
|
||||
|
||||
spin_lock_init(&priv->rx_lock);
|
||||
spin_lock_init(&priv->tx_lock);
|
||||
init_waitqueue_head(&priv->delta_msr_wait);
|
||||
/* This will push the characters through immediately rather
|
||||
than queue a task to deliver them */
|
||||
@@ -1270,6 +1284,13 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
|
||||
|
||||
dbg("%s", __FUNCTION__);
|
||||
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
priv->tx_bytes = 0;
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
spin_lock_irqsave(&priv->rx_lock, flags);
|
||||
priv->rx_bytes = 0;
|
||||
spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||||
|
||||
if (port->tty)
|
||||
port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
||||
|
||||
@@ -1372,6 +1393,7 @@ static int ftdi_write (struct usb_serial_port *port,
|
||||
int data_offset ; /* will be 1 for the SIO and 0 otherwise */
|
||||
int status;
|
||||
int transfer_size;
|
||||
unsigned long flags;
|
||||
|
||||
dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
|
||||
|
||||
@@ -1379,6 +1401,13 @@ static int ftdi_write (struct usb_serial_port *port,
|
||||
dbg("write request of 0 bytes");
|
||||
return 0;
|
||||
}
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
dbg("%s - write limit hit\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
|
||||
data_offset = priv->write_offset;
|
||||
dbg("data_offset set to %d",data_offset);
|
||||
@@ -1445,6 +1474,12 @@ static int ftdi_write (struct usb_serial_port *port,
|
||||
err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
|
||||
count = status;
|
||||
kfree (buffer);
|
||||
} else {
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
++priv->tx_outstanding_urbs;
|
||||
priv->tx_outstanding_bytes += count;
|
||||
priv->tx_bytes += count;
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
}
|
||||
|
||||
/* we are done with this urb, so let the host driver
|
||||
@@ -1460,7 +1495,11 @@ static int ftdi_write (struct usb_serial_port *port,
|
||||
|
||||
static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||
struct ftdi_private *priv;
|
||||
int data_offset; /* will be 1 for the SIO and 0 otherwise */
|
||||
unsigned long countback;
|
||||
|
||||
/* free up the transfer buffer, as usb_free_urb() does not do this */
|
||||
kfree (urb->transfer_buffer);
|
||||
@@ -1472,34 +1511,67 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
priv = usb_get_serial_port_data(port);
|
||||
if (!priv) {
|
||||
dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
/* account for transferred data */
|
||||
countback = urb->actual_length;
|
||||
data_offset = priv->write_offset;
|
||||
if (data_offset > 0) {
|
||||
/* Subtract the control bytes */
|
||||
countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ));
|
||||
}
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
--priv->tx_outstanding_urbs;
|
||||
priv->tx_outstanding_bytes -= countback;
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
|
||||
usb_serial_port_softint(port);
|
||||
} /* ftdi_write_bulk_callback */
|
||||
|
||||
|
||||
static int ftdi_write_room( struct usb_serial_port *port )
|
||||
{
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
int room;
|
||||
unsigned long flags;
|
||||
|
||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||
|
||||
/*
|
||||
* We really can take anything the user throws at us
|
||||
* but let's pick a nice big number to tell the tty
|
||||
* layer that we have lots of free space
|
||||
*/
|
||||
return 2048;
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
|
||||
/*
|
||||
* We really can take anything the user throws at us
|
||||
* but let's pick a nice big number to tell the tty
|
||||
* layer that we have lots of free space
|
||||
*/
|
||||
room = 2048;
|
||||
} else {
|
||||
room = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
return room;
|
||||
} /* ftdi_write_room */
|
||||
|
||||
|
||||
static int ftdi_chars_in_buffer (struct usb_serial_port *port)
|
||||
{ /* ftdi_chars_in_buffer */
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
int buffered;
|
||||
unsigned long flags;
|
||||
|
||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||
|
||||
/*
|
||||
* We can't really account for how much data we
|
||||
* have sent out, but hasn't made it through to the
|
||||
* device, so just tell the tty layer that everything
|
||||
* is flushed.
|
||||
*/
|
||||
return 0;
|
||||
spin_lock_irqsave(&priv->tx_lock, flags);
|
||||
buffered = (int)priv->tx_outstanding_bytes;
|
||||
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||||
if (buffered < 0) {
|
||||
err("%s outstanding tx bytes is negative!", __FUNCTION__);
|
||||
buffered = 0;
|
||||
}
|
||||
return buffered;
|
||||
} /* ftdi_chars_in_buffer */
|
||||
|
||||
|
||||
@@ -1509,6 +1581,8 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
||||
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
|
||||
struct tty_struct *tty;
|
||||
struct ftdi_private *priv;
|
||||
unsigned long countread;
|
||||
unsigned long flags;
|
||||
|
||||
if (urb->number_of_packets > 0) {
|
||||
err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
|
||||
@@ -1543,6 +1617,13 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
/* count data bytes, but not status bytes */
|
||||
countread = urb->actual_length;
|
||||
countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ);
|
||||
spin_lock_irqsave(&priv->rx_lock, flags);
|
||||
priv->rx_bytes += countread;
|
||||
spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||||
|
||||
ftdi_process_read(port);
|
||||
|
||||
} /* ftdi_read_bulk_callback */
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
#define FTDI_ACTZWAVE_PID 0xF2D0
|
||||
|
||||
|
||||
/* www.starting-point-systems.com µChameleon device */
|
||||
#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */
|
||||
|
||||
/* www.irtrans.de device */
|
||||
#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
|
||||
|
||||
@@ -179,6 +182,10 @@
|
||||
/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
|
||||
#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */
|
||||
|
||||
/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */
|
||||
|
||||
#define FTDI_TNC_X_PID 0xEBE0
|
||||
|
||||
/*
|
||||
* ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
|
||||
* All of these devices use FTDI's vendor ID (0x0403).
|
||||
@@ -442,6 +449,18 @@
|
||||
*/
|
||||
#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */
|
||||
|
||||
/*
|
||||
* ThorLabs USB motor drivers
|
||||
*/
|
||||
#define FTDI_THORLABS_PID 0xfaf0 /* ThorLabs USB motor drivers */
|
||||
|
||||
/*
|
||||
* Testo products (http://www.testo.com/)
|
||||
* Submitted by Colin Leroy
|
||||
*/
|
||||
#define TESTO_VID 0x128D
|
||||
#define TESTO_USB_INTERFACE_PID 0x0001
|
||||
|
||||
/* Commands */
|
||||
#define FTDI_SIO_RESET 0 /* Reset the port */
|
||||
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(0x1404, 0xcddc) },
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
/* the mode to be set when the port ist opened */
|
||||
static int initial_mode = 1;
|
||||
@@ -42,8 +43,6 @@ static int initial_mode = 1;
|
||||
/* debug flag */
|
||||
static int debug = 0;
|
||||
|
||||
#include "usb-serial.h"
|
||||
|
||||
#define GARMIN_VENDOR_ID 0x091E
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "usb-serial.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
@@ -285,6 +285,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
|
||||
if (result)
|
||||
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
|
||||
|
||||
void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <linux/wait.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "io_edgeport.h"
|
||||
#include "io_ionsp.h" /* info for the iosp messages */
|
||||
#include "io_16654.h" /* 16654 UART defines */
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
#include "usb-serial.h"
|
||||
#include "io_16654.h"
|
||||
#include "io_usbvend.h"
|
||||
#include "io_ti.h"
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "ipaq.h"
|
||||
|
||||
#define KP_RETRIES 100
|
||||
@@ -70,6 +70,8 @@
|
||||
|
||||
static __u16 product, vendor;
|
||||
static int debug;
|
||||
static int connect_retries = KP_RETRIES;
|
||||
static int initial_wait;
|
||||
|
||||
/* Function prototypes for an ipaq */
|
||||
static int ipaq_open (struct usb_serial_port *port, struct file *filp);
|
||||
@@ -248,6 +250,7 @@ static struct usb_device_id ipaq_id_table [] = {
|
||||
{ USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
|
||||
{ USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
|
||||
{ USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
|
||||
{ USB_DEVICE(0x04DD, 0x9102) }, /* SHARP WS003SH USB Modem */
|
||||
{ USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
|
||||
{ USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
|
||||
{ USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
|
||||
@@ -582,7 +585,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
|
||||
struct ipaq_private *priv;
|
||||
struct ipaq_packet *pkt;
|
||||
int i, result = 0;
|
||||
int retries = KP_RETRIES;
|
||||
int retries = connect_retries;
|
||||
|
||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||
|
||||
@@ -646,16 +649,12 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
|
||||
port->read_urb->transfer_buffer_length = URBDATA_SIZE;
|
||||
port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
|
||||
|
||||
msleep(1000*initial_wait);
|
||||
/* 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,
|
||||
ipaq_read_bulk_callback, port);
|
||||
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
||||
if (result) {
|
||||
err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send out control message observed in win98 sniffs. Not sure what
|
||||
@@ -670,8 +669,14 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
|
||||
usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
|
||||
0x1, 0, NULL, 0, 100);
|
||||
if (result == 0) {
|
||||
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
||||
if (result) {
|
||||
err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
msleep(1000);
|
||||
}
|
||||
err("%s - failed doing control urb, error %d", __FUNCTION__, result);
|
||||
goto error;
|
||||
@@ -854,6 +859,7 @@ static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
|
||||
|
||||
if (urb->status) {
|
||||
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&write_list_lock, flags);
|
||||
@@ -966,3 +972,9 @@ MODULE_PARM_DESC(vendor, "User specified USB idVendor");
|
||||
|
||||
module_param(product, ushort, 0);
|
||||
MODULE_PARM_DESC(product, "User specified USB idProduct");
|
||||
|
||||
module_param(connect_retries, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)");
|
||||
|
||||
module_param(initial_wait, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(initial_wait, "Time to wait before attempting a connection (in seconds)");
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "usb-serial.h"
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
@@ -373,6 +373,8 @@ static void ipw_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
|
||||
|
||||
dbg("%s", __FUNCTION__);
|
||||
|
||||
port->write_urb_busy = 0;
|
||||
|
||||
if (urb->status)
|
||||
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "keyspan.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
@@ -107,8 +108,6 @@ struct ezusb_hex_record {
|
||||
#include "xircom_pgs_fw.h"
|
||||
#endif
|
||||
|
||||
#include "usb-serial.h"
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
*/
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "kl5kusb105.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include "usb-serial.h"
|
||||
#include "kobil_sct.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "mct_u232.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
|
||||
@@ -9,39 +9,14 @@
|
||||
|
||||
Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
|
||||
|
||||
History:
|
||||
|
||||
2005-05-19 v0.1 Initial version, based on incomplete docs
|
||||
and analysis of misbehavior with the standard driver
|
||||
2005-05-20 v0.2 Extended the input buffer to avoid losing
|
||||
random 64-byte chunks of data
|
||||
2005-05-21 v0.3 implemented chars_in_buffer()
|
||||
turned on low_latency
|
||||
simplified the code somewhat
|
||||
2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load
|
||||
removed some dead code
|
||||
added sponsor notice
|
||||
coding style clean-up
|
||||
2005-06-20 v0.4.1 add missing braces :-/
|
||||
killed end-of-line whitespace
|
||||
2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2
|
||||
2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard
|
||||
2005-09-20 v0.4.4 increased recv buffer size: the card sometimes
|
||||
wants to send >2000 bytes.
|
||||
2006-04-10 v0.5 fixed two array overrun errors :-/
|
||||
2006-04-21 v0.5.1 added support for Sierra Wireless MC8755
|
||||
2006-05-15 v0.6 re-enable multi-port support
|
||||
2006-06-01 v0.6.1 add COBRA
|
||||
2006-06-01 v0.6.2 add backwards-compatibility stuff
|
||||
2006-06-01 v0.6.3 add Novatel Wireless
|
||||
2006-06-01 v0.7 Option => GSM
|
||||
History: see the git log.
|
||||
|
||||
Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
|
||||
|
||||
This driver exists because the "normal" serial driver doesn't work too well
|
||||
with GSM modems. Issues:
|
||||
- data loss -- one single Receive URB is not nearly enough
|
||||
- nonstandard flow (Option devices) and multiplex (Sierra) control
|
||||
- nonstandard flow (Option devices) control
|
||||
- controlling the baud rate doesn't make sense
|
||||
|
||||
This driver is named "option" because the most common device it's
|
||||
@@ -53,7 +28,7 @@
|
||||
device features.
|
||||
*/
|
||||
|
||||
#define DRIVER_VERSION "v0.7.0"
|
||||
#define DRIVER_VERSION "v0.7.1"
|
||||
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
|
||||
#define DRIVER_DESC "USB Driver for GSM modems"
|
||||
|
||||
@@ -64,7 +39,7 @@
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
/* Function prototypes */
|
||||
static int option_open(struct usb_serial_port *port, struct file *filp);
|
||||
@@ -95,27 +70,29 @@ static int option_send_setup(struct usb_serial_port *port);
|
||||
#define OPTION_VENDOR_ID 0x0AF0
|
||||
#define HUAWEI_VENDOR_ID 0x12D1
|
||||
#define AUDIOVOX_VENDOR_ID 0x0F3D
|
||||
#define SIERRAWIRELESS_VENDOR_ID 0x1199
|
||||
#define NOVATELWIRELESS_VENDOR_ID 0x1410
|
||||
#define ANYDATA_VENDOR_ID 0x16d5
|
||||
|
||||
#define OPTION_PRODUCT_OLD 0x5000
|
||||
#define OPTION_PRODUCT_FUSION 0x6000
|
||||
#define OPTION_PRODUCT_FUSION2 0x6300
|
||||
#define OPTION_PRODUCT_COBRA 0x6500
|
||||
#define OPTION_PRODUCT_COBRA2 0x6600
|
||||
#define HUAWEI_PRODUCT_E600 0x1001
|
||||
#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
|
||||
#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802
|
||||
#define NOVATELWIRELESS_PRODUCT_U740 0x1400
|
||||
#define ANYDATA_PRODUCT_ID 0x6501
|
||||
|
||||
static struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
|
||||
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
|
||||
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
|
||||
{ USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
|
||||
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
@@ -124,13 +101,11 @@ static struct usb_device_id option_ids1[] = {
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
|
||||
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
|
||||
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
static struct usb_device_id option_ids3[] = {
|
||||
{ USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
|
||||
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
@@ -147,37 +122,11 @@ static struct usb_driver option_driver = {
|
||||
/* The card has three separate interfaces, which the serial driver
|
||||
* recognizes separately, thus num_port=1.
|
||||
*/
|
||||
static struct usb_serial_driver option_3port_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "option",
|
||||
},
|
||||
.description = "GSM modem (3-port)",
|
||||
.id_table = option_ids3,
|
||||
.num_interrupt_in = NUM_DONT_CARE,
|
||||
.num_bulk_in = NUM_DONT_CARE,
|
||||
.num_bulk_out = NUM_DONT_CARE,
|
||||
.num_ports = 3,
|
||||
.open = option_open,
|
||||
.close = option_close,
|
||||
.write = option_write,
|
||||
.write_room = option_write_room,
|
||||
.chars_in_buffer = option_chars_in_buffer,
|
||||
.throttle = option_rx_throttle,
|
||||
.unthrottle = option_rx_unthrottle,
|
||||
.set_termios = option_set_termios,
|
||||
.break_ctl = option_break_ctl,
|
||||
.tiocmget = option_tiocmget,
|
||||
.tiocmset = option_tiocmset,
|
||||
.attach = option_startup,
|
||||
.shutdown = option_shutdown,
|
||||
.read_int_callback = option_instat_callback,
|
||||
};
|
||||
|
||||
static struct usb_serial_driver option_1port_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "option",
|
||||
.name = "option1",
|
||||
},
|
||||
.description = "GSM modem (1-port)",
|
||||
.id_table = option_ids1,
|
||||
@@ -241,9 +190,6 @@ static int __init option_init(void)
|
||||
retval = usb_serial_register(&option_1port_device);
|
||||
if (retval)
|
||||
goto failed_1port_device_register;
|
||||
retval = usb_serial_register(&option_3port_device);
|
||||
if (retval)
|
||||
goto failed_3port_device_register;
|
||||
retval = usb_register(&option_driver);
|
||||
if (retval)
|
||||
goto failed_driver_register;
|
||||
@@ -253,8 +199,6 @@ static int __init option_init(void)
|
||||
return 0;
|
||||
|
||||
failed_driver_register:
|
||||
usb_serial_deregister (&option_3port_device);
|
||||
failed_3port_device_register:
|
||||
usb_serial_deregister (&option_1port_device);
|
||||
failed_1port_device_register:
|
||||
return retval;
|
||||
@@ -263,7 +207,6 @@ failed_1port_device_register:
|
||||
static void __exit option_exit(void)
|
||||
{
|
||||
usb_deregister (&option_driver);
|
||||
usb_serial_deregister (&option_3port_device);
|
||||
usb_serial_deregister (&option_1port_device);
|
||||
}
|
||||
|
||||
@@ -652,7 +595,6 @@ static void option_setup_urbs(struct usb_serial *serial)
|
||||
|
||||
dbg("%s", __FUNCTION__);
|
||||
|
||||
|
||||
for (i = 0; i < serial->num_ports; i++) {
|
||||
port = serial->port[i];
|
||||
portdata = usb_get_serial_port_data(port);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "pl2303.h"
|
||||
|
||||
/*
|
||||
@@ -52,6 +52,7 @@ struct pl2303_buf {
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
|
||||
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
|
||||
@@ -79,6 +80,8 @@ static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
|
||||
{ USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) },
|
||||
{ USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
|
||||
{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define PL2303_VENDOR_ID 0x067b
|
||||
#define PL2303_PRODUCT_ID 0x2303
|
||||
#define PL2303_PRODUCT_ID_RSAQ2 0x04bb
|
||||
#define PL2303_PRODUCT_ID_DCU11 0x1234
|
||||
#define PL2303_PRODUCT_ID_PHAROS 0xaaa0
|
||||
#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2
|
||||
|
||||
@@ -84,3 +85,11 @@
|
||||
/* Ours Technology Inc DKU-5 clone, chipset: Prolific Technology Inc */
|
||||
#define OTI_VENDOR_ID 0x0ea0
|
||||
#define OTI_PRODUCT_ID 0x6858
|
||||
|
||||
/* DATAPILOT Universal-2 Phone Cable */
|
||||
#define DATAPILOT_U2_VENDOR_ID 0x0731
|
||||
#define DATAPILOT_U2_PRODUCT_ID 0x2003
|
||||
|
||||
/* Belkin "F5U257" Serial Adapter */
|
||||
#define BELKIN_VENDOR_ID 0x050d
|
||||
#define BELKIN_PRODUCT_ID 0x0257
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
|
||||
#ifndef CONFIG_USB_SAFE_PADDED
|
||||
|
||||
75
drivers/usb/serial/sierra.c
Normal file
75
drivers/usb/serial/sierra.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Sierra Wireless CDMA Wireless Serial USB driver
|
||||
*
|
||||
* Current Copy modified by: Kevin Lloyd <linux@sierrawireless.com>
|
||||
* Original Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
|
||||
{ USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
|
||||
{ USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
|
||||
{ USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
|
||||
{ USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
|
||||
{ USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
|
||||
{ USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
|
||||
{ USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
|
||||
/* Following devices are supported in the airprime.c driver */
|
||||
/* { USB_DEVICE(0x1199, 0x0112) }, */ /* Sierra Wireless AirCard 580 */
|
||||
/* { USB_DEVICE(0x0F3D, 0x0112) }, */ /* AirPrime/Sierra PC 5220 */
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, id_table);
|
||||
|
||||
static struct usb_driver sierra_driver = {
|
||||
.name = "sierra_wireless",
|
||||
.probe = usb_serial_probe,
|
||||
.disconnect = usb_serial_disconnect,
|
||||
.id_table = id_table,
|
||||
};
|
||||
|
||||
static struct usb_serial_driver sierra_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "Sierra_Wireless",
|
||||
},
|
||||
.id_table = id_table,
|
||||
.num_interrupt_in = NUM_DONT_CARE,
|
||||
.num_bulk_in = NUM_DONT_CARE,
|
||||
.num_bulk_out = NUM_DONT_CARE,
|
||||
.num_ports = 3,
|
||||
};
|
||||
|
||||
static int __init sierra_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = usb_serial_register(&sierra_device);
|
||||
if (retval)
|
||||
return retval;
|
||||
retval = usb_register(&sierra_driver);
|
||||
if (retval)
|
||||
usb_serial_deregister(&sierra_device);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit sierra_exit(void)
|
||||
{
|
||||
usb_deregister(&sierra_driver);
|
||||
usb_serial_deregister(&sierra_device);
|
||||
}
|
||||
|
||||
module_init(sierra_init);
|
||||
module_exit(sierra_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -83,8 +83,8 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
#include "usb-serial.h"
|
||||
#include "ti_usb_3410_5052.h"
|
||||
#include "ti_fw_3410.h" /* firmware image for 3410 */
|
||||
#include "ti_fw_5052.h" /* firmware image for 5052 */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <linux/smp_lock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "pl2303.h"
|
||||
|
||||
/*
|
||||
@@ -40,6 +40,8 @@
|
||||
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
|
||||
#define DRIVER_DESC "USB Serial Driver core"
|
||||
|
||||
static void port_free(struct usb_serial_port *port);
|
||||
|
||||
/* Driver structure we register with the USB core */
|
||||
static struct usb_driver usb_serial_driver = {
|
||||
.name = "usbserial",
|
||||
@@ -146,23 +148,10 @@ static void destroy_serial(struct kref *kref)
|
||||
port = serial->port[i];
|
||||
if (!port)
|
||||
continue;
|
||||
usb_kill_urb(port->read_urb);
|
||||
usb_free_urb(port->read_urb);
|
||||
usb_kill_urb(port->write_urb);
|
||||
usb_free_urb(port->write_urb);
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
usb_free_urb(port->interrupt_in_urb);
|
||||
usb_kill_urb(port->interrupt_out_urb);
|
||||
usb_free_urb(port->interrupt_out_urb);
|
||||
kfree(port->bulk_in_buffer);
|
||||
kfree(port->bulk_out_buffer);
|
||||
kfree(port->interrupt_in_buffer);
|
||||
kfree(port->interrupt_out_buffer);
|
||||
port_free(port);
|
||||
}
|
||||
}
|
||||
|
||||
flush_scheduled_work(); /* port->work */
|
||||
|
||||
usb_put_dev(serial->dev);
|
||||
|
||||
/* free up any memory that we allocated */
|
||||
@@ -564,6 +553,11 @@ static void port_release(struct device *dev)
|
||||
struct usb_serial_port *port = to_usb_serial_port(dev);
|
||||
|
||||
dbg ("%s - %s", __FUNCTION__, dev->bus_id);
|
||||
port_free(port);
|
||||
}
|
||||
|
||||
static void port_free(struct usb_serial_port *port)
|
||||
{
|
||||
usb_kill_urb(port->read_urb);
|
||||
usb_free_urb(port->read_urb);
|
||||
usb_kill_urb(port->write_urb);
|
||||
@@ -576,6 +570,7 @@ static void port_release(struct device *dev)
|
||||
kfree(port->bulk_out_buffer);
|
||||
kfree(port->interrupt_in_buffer);
|
||||
kfree(port->interrupt_out_buffer);
|
||||
flush_scheduled_work(); /* port->work */
|
||||
kfree(port);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* USB Serial Converter driver
|
||||
*
|
||||
* Copyright (C) 1999 - 2005
|
||||
* 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __LINUX_USB_SERIAL_H
|
||||
#define __LINUX_USB_SERIAL_H
|
||||
|
||||
#include <linux/kref.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */
|
||||
#define SERIAL_TTY_MINORS 255 /* loads of devices :) */
|
||||
|
||||
#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */
|
||||
|
||||
/* parity check flag */
|
||||
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
|
||||
|
||||
/**
|
||||
* usb_serial_port: structure for the specific ports of a device.
|
||||
* @serial: pointer back to the struct usb_serial owner of this port.
|
||||
* @tty: pointer to the corresponding tty for this port.
|
||||
* @lock: spinlock to grab when updating portions of this structure.
|
||||
* @mutex: mutex used to synchronize serial_open() and serial_close()
|
||||
* access for this port.
|
||||
* @number: the number of the port (the minor number).
|
||||
* @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
|
||||
* @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
|
||||
* @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe
|
||||
* for this port.
|
||||
* @interrupt_out_buffer: pointer to the interrupt out buffer for this port.
|
||||
* @interrupt_out_size: the size of the interrupt_out_buffer, in bytes.
|
||||
* @interrupt_out_urb: pointer to the interrupt out struct urb for this port.
|
||||
* @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe
|
||||
* for this port.
|
||||
* @bulk_in_buffer: pointer to the bulk in buffer for this port.
|
||||
* @read_urb: pointer to the bulk in struct urb for this port.
|
||||
* @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this
|
||||
* port.
|
||||
* @bulk_out_buffer: pointer to the bulk out buffer for this port.
|
||||
* @bulk_out_size: the size of the bulk_out_buffer, in bytes.
|
||||
* @write_urb: pointer to the bulk out struct urb for this port.
|
||||
* @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
|
||||
* port.
|
||||
* @write_wait: a wait_queue_head_t used by the port.
|
||||
* @work: work queue entry for the line discipline waking up.
|
||||
* @open_count: number of times this port has been opened.
|
||||
*
|
||||
* This structure is used by the usb-serial core and drivers for the specific
|
||||
* ports of a device.
|
||||
*/
|
||||
struct usb_serial_port {
|
||||
struct usb_serial * serial;
|
||||
struct tty_struct * tty;
|
||||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
unsigned char number;
|
||||
|
||||
unsigned char * interrupt_in_buffer;
|
||||
struct urb * interrupt_in_urb;
|
||||
__u8 interrupt_in_endpointAddress;
|
||||
|
||||
unsigned char * interrupt_out_buffer;
|
||||
int interrupt_out_size;
|
||||
struct urb * interrupt_out_urb;
|
||||
__u8 interrupt_out_endpointAddress;
|
||||
|
||||
unsigned char * bulk_in_buffer;
|
||||
int bulk_in_size;
|
||||
struct urb * read_urb;
|
||||
__u8 bulk_in_endpointAddress;
|
||||
|
||||
unsigned char * bulk_out_buffer;
|
||||
int bulk_out_size;
|
||||
struct urb * write_urb;
|
||||
int write_urb_busy;
|
||||
__u8 bulk_out_endpointAddress;
|
||||
|
||||
wait_queue_head_t write_wait;
|
||||
struct work_struct work;
|
||||
int open_count;
|
||||
struct device dev;
|
||||
};
|
||||
#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
|
||||
|
||||
/* get and set the port private data pointer helper functions */
|
||||
static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
|
||||
{
|
||||
return dev_get_drvdata(&port->dev);
|
||||
}
|
||||
|
||||
static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
|
||||
{
|
||||
dev_set_drvdata(&port->dev, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_serial - structure used by the usb-serial core for a device
|
||||
* @dev: pointer to the struct usb_device for this device
|
||||
* @type: pointer to the struct usb_serial_driver for this device
|
||||
* @interface: pointer to the struct usb_interface for this device
|
||||
* @minor: the starting minor number for this device
|
||||
* @num_ports: the number of ports this device has
|
||||
* @num_interrupt_in: number of interrupt in endpoints we have
|
||||
* @num_interrupt_out: number of interrupt out endpoints we have
|
||||
* @num_bulk_in: number of bulk in endpoints we have
|
||||
* @num_bulk_out: number of bulk out endpoints we have
|
||||
* @port: array of struct usb_serial_port structures for the different ports.
|
||||
* @private: place to put any driver specific information that is needed. The
|
||||
* usb-serial driver is required to manage this data, the usb-serial core
|
||||
* will not touch this. Use usb_get_serial_data() and
|
||||
* usb_set_serial_data() to access this.
|
||||
*/
|
||||
struct usb_serial {
|
||||
struct usb_device * dev;
|
||||
struct usb_serial_driver * type;
|
||||
struct usb_interface * interface;
|
||||
unsigned char minor;
|
||||
unsigned char num_ports;
|
||||
unsigned char num_port_pointers;
|
||||
char num_interrupt_in;
|
||||
char num_interrupt_out;
|
||||
char num_bulk_in;
|
||||
char num_bulk_out;
|
||||
struct usb_serial_port * port[MAX_NUM_PORTS];
|
||||
struct kref kref;
|
||||
void * private;
|
||||
};
|
||||
#define to_usb_serial(d) container_of(d, struct usb_serial, kref)
|
||||
|
||||
#define NUM_DONT_CARE (-1)
|
||||
|
||||
/* get and set the serial private data pointer helper functions */
|
||||
static inline void *usb_get_serial_data (struct usb_serial *serial)
|
||||
{
|
||||
return serial->private;
|
||||
}
|
||||
|
||||
static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
|
||||
{
|
||||
serial->private = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_serial_driver - describes a usb serial driver
|
||||
* @description: pointer to a string that describes this driver. This string used
|
||||
* in the syslog messages when a device is inserted or removed.
|
||||
* @id_table: pointer to a list of usb_device_id structures that define all
|
||||
* of the devices this structure can support.
|
||||
* @num_interrupt_in: the number of interrupt in endpoints this device will
|
||||
* have.
|
||||
* @num_interrupt_out: the number of interrupt out endpoints this device will
|
||||
* have.
|
||||
* @num_bulk_in: the number of bulk in endpoints this device will have.
|
||||
* @num_bulk_out: the number of bulk out endpoints this device will have.
|
||||
* @num_ports: the number of different ports this device will have.
|
||||
* @calc_num_ports: pointer to a function to determine how many ports this
|
||||
* device has dynamically. It will be called after the probe()
|
||||
* callback is called, but before attach()
|
||||
* @probe: pointer to the driver's probe function.
|
||||
* This will be called when the device is inserted into the system,
|
||||
* but before the device has been fully initialized by the usb_serial
|
||||
* subsystem. Use this function to download any firmware to the device,
|
||||
* or any other early initialization that might be needed.
|
||||
* Return 0 to continue on with the initialization sequence. Anything
|
||||
* else will abort it.
|
||||
* @attach: pointer to the driver's attach function.
|
||||
* This will be called when the struct usb_serial structure is fully set
|
||||
* set up. Do any local initialization of the device, or any private
|
||||
* memory structure allocation at this point in time.
|
||||
* @shutdown: pointer to the driver's shutdown function. This will be
|
||||
* called when the device is removed from the system.
|
||||
*
|
||||
* This structure is defines a USB Serial driver. It provides all of
|
||||
* the information that the USB serial core code needs. If the function
|
||||
* pointers are defined, then the USB serial core code will call them when
|
||||
* the corresponding tty port functions are called. If they are not
|
||||
* called, the generic serial function will be used instead.
|
||||
*
|
||||
* The driver.owner field should be set to the module owner of this driver.
|
||||
* The driver.name field should be set to the name of this driver (remember
|
||||
* it will show up in sysfs, so it needs to be short and to the point.
|
||||
* Useing the module name is a good idea.)
|
||||
*/
|
||||
struct usb_serial_driver {
|
||||
const char *description;
|
||||
const struct usb_device_id *id_table;
|
||||
char num_interrupt_in;
|
||||
char num_interrupt_out;
|
||||
char num_bulk_in;
|
||||
char num_bulk_out;
|
||||
char num_ports;
|
||||
|
||||
struct list_head driver_list;
|
||||
struct device_driver driver;
|
||||
|
||||
int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
|
||||
int (*attach) (struct usb_serial *serial);
|
||||
int (*calc_num_ports) (struct usb_serial *serial);
|
||||
|
||||
void (*shutdown) (struct usb_serial *serial);
|
||||
|
||||
int (*port_probe) (struct usb_serial_port *port);
|
||||
int (*port_remove) (struct usb_serial_port *port);
|
||||
|
||||
/* serial function calls */
|
||||
int (*open) (struct usb_serial_port *port, struct file * filp);
|
||||
void (*close) (struct usb_serial_port *port, struct file * filp);
|
||||
int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count);
|
||||
int (*write_room) (struct usb_serial_port *port);
|
||||
int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
|
||||
void (*set_termios) (struct usb_serial_port *port, struct termios * old);
|
||||
void (*break_ctl) (struct usb_serial_port *port, int break_state);
|
||||
int (*chars_in_buffer) (struct usb_serial_port *port);
|
||||
void (*throttle) (struct usb_serial_port *port);
|
||||
void (*unthrottle) (struct usb_serial_port *port);
|
||||
int (*tiocmget) (struct usb_serial_port *port, struct file *file);
|
||||
int (*tiocmset) (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
|
||||
|
||||
void (*read_int_callback)(struct urb *urb, struct pt_regs *regs);
|
||||
void (*write_int_callback)(struct urb *urb, struct pt_regs *regs);
|
||||
void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
|
||||
void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
|
||||
};
|
||||
#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
|
||||
|
||||
extern int usb_serial_register(struct usb_serial_driver *driver);
|
||||
extern void usb_serial_deregister(struct usb_serial_driver *driver);
|
||||
extern void usb_serial_port_softint(struct usb_serial_port *port);
|
||||
|
||||
extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
|
||||
extern void usb_serial_disconnect(struct usb_interface *iface);
|
||||
|
||||
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);
|
||||
|
||||
/* USB Serial console functions */
|
||||
#ifdef CONFIG_USB_SERIAL_CONSOLE
|
||||
extern void usb_serial_console_init (int debug, int minor);
|
||||
extern void usb_serial_console_exit (void);
|
||||
extern void usb_serial_console_disconnect(struct usb_serial *serial);
|
||||
#else
|
||||
static inline void usb_serial_console_init (int debug, int minor) { }
|
||||
static inline void usb_serial_console_exit (void) { }
|
||||
static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
|
||||
#endif
|
||||
|
||||
/* Functions needed by other parts of the usbserial core */
|
||||
extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
|
||||
extern void usb_serial_put(struct usb_serial *serial);
|
||||
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, 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, struct pt_regs *regs);
|
||||
extern void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
|
||||
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 int usb_serial_bus_register (struct usb_serial_driver *device);
|
||||
extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
|
||||
|
||||
extern struct usb_serial_driver usb_serial_generic_device;
|
||||
extern struct bus_type usb_serial_bus_type;
|
||||
extern struct tty_driver *usb_serial_tty_driver;
|
||||
|
||||
static inline void usb_serial_debug_data(int debug,
|
||||
struct device *dev,
|
||||
const char *function, int size,
|
||||
const unsigned char *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (debug) {
|
||||
dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ", function, size);
|
||||
for (i = 0; i < size; ++i)
|
||||
printk ("%.2x ", data[i]);
|
||||
printk ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Use our own dbg macro */
|
||||
#undef dbg
|
||||
#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0)
|
||||
|
||||
|
||||
|
||||
#endif /* ifdef __LINUX_USB_SERIAL_H */
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "visor.h"
|
||||
|
||||
/*
|
||||
@@ -302,7 +302,6 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->bytes_in = 0;
|
||||
priv->bytes_out = 0;
|
||||
priv->outstanding_urbs = 0;
|
||||
priv->throttled = 0;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
@@ -435,13 +434,25 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
|
||||
|
||||
static int visor_write_room (struct usb_serial_port *port)
|
||||
{
|
||||
struct visor_private *priv = usb_get_serial_port_data(port);
|
||||
unsigned long flags;
|
||||
|
||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||
|
||||
/*
|
||||
* We really can take anything the user throws at us
|
||||
* but let's pick a nice big number to tell the tty
|
||||
* layer that we have lots of free space
|
||||
* layer that we have lots of free space, unless we don't.
|
||||
*/
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
dbg("%s - write limit hit\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return 2048;
|
||||
}
|
||||
|
||||
@@ -758,15 +769,22 @@ static int visor_calc_num_ports (struct usb_serial *serial)
|
||||
|
||||
static int generic_startup(struct usb_serial *serial)
|
||||
{
|
||||
struct usb_serial_port **ports = serial->port;
|
||||
struct visor_private *priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < serial->num_ports; ++i) {
|
||||
priv = kzalloc (sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
if (!priv) {
|
||||
while (i-- != 0) {
|
||||
priv = usb_get_serial_port_data(ports[i]);
|
||||
usb_set_serial_port_data(ports[i], NULL);
|
||||
kfree(priv);
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
spin_lock_init(&priv->lock);
|
||||
usb_set_serial_port_data(serial->port[i], priv);
|
||||
usb_set_serial_port_data(ports[i], priv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -876,7 +894,18 @@ static int clie_5_attach (struct usb_serial *serial)
|
||||
|
||||
static void visor_shutdown (struct usb_serial *serial)
|
||||
{
|
||||
struct visor_private *priv;
|
||||
int i;
|
||||
|
||||
dbg("%s", __FUNCTION__);
|
||||
|
||||
for (i = 0; i < serial->num_ports; i++) {
|
||||
priv = usb_get_serial_port_data(serial->port[i]);
|
||||
if (priv) {
|
||||
usb_set_serial_port_data(serial->port[i], NULL);
|
||||
kfree(priv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/serial.h>
|
||||
#include "usb-serial.h"
|
||||
#include <linux/usb/serial.h>
|
||||
#include "whiteheat_fw.h" /* firmware for the ConnectTech WhiteHEAT device */
|
||||
#include "whiteheat.h" /* WhiteHEAT specific commands */
|
||||
|
||||
|
||||
@@ -112,13 +112,11 @@ static int slave_configure(struct scsi_device *sdev)
|
||||
if (sdev->scsi_level < SCSI_2)
|
||||
sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
|
||||
|
||||
/* According to the technical support people at Genesys Logic,
|
||||
* devices using their chips have problems transferring more than
|
||||
* 32 KB at a time. In practice people have found that 64 KB
|
||||
* works okay and that's what Windows does. But we'll be
|
||||
* conservative; people can always use the sysfs interface to
|
||||
* increase max_sectors. */
|
||||
if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS &&
|
||||
/* Many devices have trouble transfering more than 32KB at a time,
|
||||
* while others have trouble with more than 64K. At this time we
|
||||
* are limiting both to 32K (64 sectores).
|
||||
*/
|
||||
if ((us->flags & US_FL_MAX_SECTORS_64) &&
|
||||
sdev->request_queue->max_sectors > 64)
|
||||
blk_queue_max_sectors(sdev->request_queue, 64);
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
|
||||
if (timeleft <= 0) {
|
||||
US_DEBUGP("%s -- cancelling URB\n",
|
||||
timeleft == 0 ? "Timeout" : "Signal");
|
||||
usb_unlink_urb(us->current_urb);
|
||||
usb_kill_urb(us->current_urb);
|
||||
}
|
||||
|
||||
/* return the URB status */
|
||||
|
||||
@@ -112,6 +112,19 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_FIX_INQUIRY ),
|
||||
|
||||
/* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */
|
||||
UNUSUAL_DEV( 0x0419, 0x0100, 0x0100, 0x0100,
|
||||
"Samsung Info. Systems America, Inc.",
|
||||
"MP3 Player",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Orgad Shaneh <orgads@gmail.com> */
|
||||
UNUSUAL_DEV( 0x0419, 0xaace, 0x0100, 0x0100,
|
||||
"Samsung", "MP3 Player",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Christian Leber <christian@leber.de> */
|
||||
UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100,
|
||||
"TrekStor",
|
||||
@@ -132,6 +145,21 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100,
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Mario Rettig <mariorettig@web.de> */
|
||||
UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
|
||||
"Nokia",
|
||||
"Nokia 3250",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
|
||||
|
||||
/* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and
|
||||
* Einar Th. Einarsson <einarthered@gmail.com> */
|
||||
UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100,
|
||||
"Nokia",
|
||||
"N91",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
|
||||
|
||||
/* Reported by Jiri Slaby <jirislaby@gmail.com> and
|
||||
* Rene C. Castberg <Rene@Castberg.org> */
|
||||
UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100,
|
||||
@@ -140,6 +168,13 @@ UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100,
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
|
||||
|
||||
/* Reported by Matthew Bloch <matthew@bytemark.co.uk> */
|
||||
UNUSUAL_DEV( 0x0421, 0x044e, 0x0100, 0x0100,
|
||||
"Nokia",
|
||||
"E61",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
|
||||
|
||||
/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
|
||||
UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210,
|
||||
"SMSC",
|
||||
@@ -473,10 +508,11 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
|
||||
US_SC_SCSI, US_PR_DEVICE, NULL,
|
||||
US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
|
||||
|
||||
/* This entry is needed because the device reports Sub=ff */
|
||||
UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0600,
|
||||
/* Submitted by Lars Jacob <jacob.lars@googlemail.com>
|
||||
* This entry is needed because the device reports Sub=ff */
|
||||
UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0610,
|
||||
"Sony",
|
||||
"DSC-T1/T5",
|
||||
"DSC-T1/T5/H5",
|
||||
US_SC_8070, US_PR_DEVICE, NULL,
|
||||
US_FL_SINGLE_LUN ),
|
||||
|
||||
@@ -598,18 +634,6 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210,
|
||||
"Digital Camera EX-20 DSC",
|
||||
US_SC_8070, US_PR_DEVICE, NULL, 0 ),
|
||||
|
||||
/* The entry was here before I took over, and had US_SC_RBC. It turns
|
||||
* out that isn't needed. Additionally, Torsten Eriksson
|
||||
* <Torsten.Eriksson@bergianska.se> is able to use his device fine
|
||||
* without this entry at all - but I don't suspect that will be true
|
||||
* for all users (the protocol is likely needed), so is staying at
|
||||
* this time. - Phil Dibowitz <phil@ipom.com>
|
||||
*/
|
||||
UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
|
||||
"LaCie",
|
||||
"USB Hard Disk",
|
||||
US_SC_DEVICE, US_PR_CB, NULL, 0 ),
|
||||
|
||||
/* Submitted by Joel Bourquard <numlock@freesurf.ch>
|
||||
* Some versions of this device need the SubClass and Protocol overrides
|
||||
* while others don't.
|
||||
@@ -708,18 +732,22 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113,
|
||||
* They were originally reported by Alexander Oltu
|
||||
* <alexander@all-2.com> and Peter Marks <peter.marks@turner.com>
|
||||
* respectively.
|
||||
*
|
||||
* US_FL_GO_SLOW and US_FL_MAX_SECTORS_64 added by Phil Dibowitz
|
||||
* <phil@ipom.com> as these flags were made and hard-coded
|
||||
* special-cases were pulled from scsiglue.c.
|
||||
*/
|
||||
UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff,
|
||||
"Genesys Logic",
|
||||
"USB to IDE Optical",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_GO_SLOW ),
|
||||
US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
|
||||
|
||||
UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff,
|
||||
"Genesys Logic",
|
||||
"USB to IDE Disk",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_GO_SLOW ),
|
||||
US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
|
||||
|
||||
/* Reported by Hanno Boeck <hanno@gmx.de>
|
||||
* Taken from the Lycoris Kernel */
|
||||
@@ -1073,7 +1101,15 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
|
||||
"Optio S/S4",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_FIX_INQUIRY ),
|
||||
|
||||
|
||||
/* This is a virtual windows driver CD, which the zd1211rw driver automatically
|
||||
* converts into a WLAN device. */
|
||||
UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
|
||||
"ZyXEL",
|
||||
"G-220F USB-WLAN Install",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_DEVICE ),
|
||||
|
||||
#ifdef CONFIG_USB_STORAGE_ISD200
|
||||
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
|
||||
"ATI",
|
||||
@@ -1196,6 +1232,14 @@ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110,
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Benjamin Schiller <sbenni@gmx.de>
|
||||
* It is also sold by Easylite as DJ 20 */
|
||||
UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103,
|
||||
"Typhoon",
|
||||
"My DJ 1820",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64),
|
||||
|
||||
/* Reported by Michael Stattmann <michael@stattmann.com> */
|
||||
UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
|
||||
"Sony Ericsson",
|
||||
@@ -1227,6 +1271,15 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
|
||||
* and Renato Perini <rperini@email.it>
|
||||
*/
|
||||
UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001,
|
||||
"Motorola",
|
||||
"RAZR V3x",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
|
||||
UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
|
||||
"MPIO",
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/utsrelease.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
@@ -373,8 +374,12 @@ static int usb_stor_control_thread(void * __us)
|
||||
/* lock access to the state */
|
||||
scsi_lock(host);
|
||||
|
||||
/* did the command already complete because of a disconnect? */
|
||||
if (!us->srb)
|
||||
; /* nothing to do */
|
||||
|
||||
/* indicate that the command is done */
|
||||
if (us->srb->result != DID_ABORT << 16) {
|
||||
else if (us->srb->result != DID_ABORT << 16) {
|
||||
US_DEBUGP("scsi cmd done, result=0x%x\n",
|
||||
us->srb->result);
|
||||
us->srb->scsi_done(us->srb);
|
||||
@@ -478,7 +483,7 @@ static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
|
||||
}
|
||||
|
||||
/* Get the unusual_devs entries and the string descriptors */
|
||||
static void get_device_info(struct us_data *us, const struct usb_device_id *id)
|
||||
static int get_device_info(struct us_data *us, const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *dev = us->pusb_dev;
|
||||
struct usb_interface_descriptor *idesc =
|
||||
@@ -495,6 +500,11 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
|
||||
unusual_dev->useTransport;
|
||||
us->flags = USB_US_ORIG_FLAGS(id->driver_info);
|
||||
|
||||
if (us->flags & US_FL_IGNORE_DEVICE) {
|
||||
printk(KERN_INFO USB_STORAGE "device ignored\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* This flag is only needed when we're in high-speed, so let's
|
||||
* disable it if we're in full-speed
|
||||
@@ -524,7 +534,8 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
|
||||
if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
|
||||
printk(KERN_NOTICE USB_STORAGE "This device "
|
||||
"(%04x,%04x,%04x S %02x P %02x)"
|
||||
" has %s in unusual_devs.h\n"
|
||||
" has %s in unusual_devs.h (kernel"
|
||||
" %s)\n"
|
||||
" Please send a copy of this message to "
|
||||
"<linux-usb-devel@lists.sourceforge.net>\n",
|
||||
le16_to_cpu(ddesc->idVendor),
|
||||
@@ -532,8 +543,11 @@ static void get_device_info(struct us_data *us, const struct usb_device_id *id)
|
||||
le16_to_cpu(ddesc->bcdDevice),
|
||||
idesc->bInterfaceSubClass,
|
||||
idesc->bInterfaceProtocol,
|
||||
msgs[msg]);
|
||||
msgs[msg],
|
||||
UTS_RELEASE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the transport settings */
|
||||
@@ -836,32 +850,34 @@ static void dissociate_dev(struct us_data *us)
|
||||
* the host */
|
||||
static void quiesce_and_remove_host(struct us_data *us)
|
||||
{
|
||||
struct Scsi_Host *host = us_to_host(us);
|
||||
|
||||
/* Prevent new USB transfers, stop the current command, and
|
||||
* interrupt a SCSI-scan or device-reset delay */
|
||||
scsi_lock(host);
|
||||
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
|
||||
scsi_unlock(host);
|
||||
usb_stor_stop_transport(us);
|
||||
wake_up(&us->delay_wait);
|
||||
|
||||
/* It doesn't matter if the SCSI-scanning thread is still running.
|
||||
* The thread will exit when it sees the DISCONNECTING flag. */
|
||||
|
||||
/* Wait for the current command to finish, then remove the host */
|
||||
mutex_lock(&us->dev_mutex);
|
||||
mutex_unlock(&us->dev_mutex);
|
||||
|
||||
/* queuecommand won't accept any new commands and the control
|
||||
* thread won't execute a previously-queued command. If there
|
||||
* is such a command pending, complete it with an error. */
|
||||
mutex_lock(&us->dev_mutex);
|
||||
if (us->srb) {
|
||||
us->srb->result = DID_NO_CONNECT << 16;
|
||||
scsi_lock(us_to_host(us));
|
||||
scsi_lock(host);
|
||||
us->srb->scsi_done(us->srb);
|
||||
us->srb = NULL;
|
||||
scsi_unlock(us_to_host(us));
|
||||
scsi_unlock(host);
|
||||
}
|
||||
mutex_unlock(&us->dev_mutex);
|
||||
|
||||
/* Now we own no commands so it's safe to remove the SCSI host */
|
||||
scsi_remove_host(us_to_host(us));
|
||||
scsi_remove_host(host);
|
||||
}
|
||||
|
||||
/* Second stage of disconnect processing: deallocate all resources */
|
||||
@@ -960,7 +976,9 @@ static int storage_probe(struct usb_interface *intf,
|
||||
* of the match from the usb_device_id table, so we can find the
|
||||
* corresponding entry in the private table.
|
||||
*/
|
||||
get_device_info(us, id);
|
||||
result = get_device_info(us, id);
|
||||
if (result)
|
||||
goto BadDevice;
|
||||
|
||||
/* Get the transport, protocol, and pipe settings */
|
||||
result = get_transport(us);
|
||||
|
||||
@@ -176,8 +176,4 @@ extern void fill_inquiry_response(struct us_data *us,
|
||||
#define scsi_unlock(host) spin_unlock_irq(host->host_lock)
|
||||
#define scsi_lock(host) spin_lock_irq(host->host_lock)
|
||||
|
||||
|
||||
/* Vendor ID list for devices that require special handling */
|
||||
#define USB_VENDOR_ID_GENESYS 0x05e3 /* Genesys Logic */
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user