提交 e90a4e47 编写于 作者: L Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (22 commits)
  USB: atmel_usba_udc fixes, mostly disconnect()
  USB: pxa27x_udc: minor fixes
  usbtest: comment on why this code "expects" negative and positive errnos
  USB: remove PICDEM FS USB demo (04d8:000c) device from ldusb
  USB: option: add new Dell 5520 HSDPA variant
  USB: unusual_devs: Add support for GI 0401 SD-Card interface
  USB: serial gadget: descriptor cleanup
  USB: serial gadget: simplify endpoint handling
  USB: serial gadget: remove needless data structure
  USB: serial gadget: cleanup/reorg
  usb: fix compile warning in isp1760
  USB: do not handle device 1410:5010 in 'option' driver
  USB: Fix unusual_devs.h ordering
  USB: add Zoom Telephonics Model 3095F V.92 USB Mini External modem to cdc-acm
  USB: Support for the ET502HS HDSPA modem in option driver
  USB: Support for the ET502HS HDSPA modem
  usb: fix integer as NULL pointer warnings found by sparse
  USB: isp1760: fix printk format
  USB: add Telstra NextG CDMA id to option driver
  USB: add association.h
  ...
...@@ -1248,6 +1248,9 @@ static struct usb_device_id acm_ids[] = { ...@@ -1248,6 +1248,9 @@ static struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */ { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
}, },
{ USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
/* control interfaces with various AT-command sets */ /* control interfaces with various AT-command sets */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
......
...@@ -156,6 +156,10 @@ static struct attribute *ep_dev_attrs[] = { ...@@ -156,6 +156,10 @@ static struct attribute *ep_dev_attrs[] = {
static struct attribute_group ep_dev_attr_grp = { static struct attribute_group ep_dev_attr_grp = {
.attrs = ep_dev_attrs, .attrs = ep_dev_attrs,
}; };
static struct attribute_group *ep_dev_groups[] = {
&ep_dev_attr_grp,
NULL
};
static int usb_endpoint_major_init(void) static int usb_endpoint_major_init(void)
{ {
...@@ -298,6 +302,7 @@ int usb_create_ep_files(struct device *parent, ...@@ -298,6 +302,7 @@ int usb_create_ep_files(struct device *parent,
ep_dev->desc = &endpoint->desc; ep_dev->desc = &endpoint->desc;
ep_dev->udev = udev; ep_dev->udev = udev;
ep_dev->dev.groups = ep_dev_groups;
ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor); ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor);
ep_dev->dev.class = ep_class->class; ep_dev->dev.class = ep_class->class;
ep_dev->dev.parent = parent; ep_dev->dev.parent = parent;
...@@ -309,9 +314,6 @@ int usb_create_ep_files(struct device *parent, ...@@ -309,9 +314,6 @@ int usb_create_ep_files(struct device *parent,
retval = device_register(&ep_dev->dev); retval = device_register(&ep_dev->dev);
if (retval) if (retval)
goto error_chrdev; goto error_chrdev;
retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
if (retval)
goto error_group;
/* create the symlink to the old-style "ep_XX" directory */ /* create the symlink to the old-style "ep_XX" directory */
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
...@@ -322,8 +324,6 @@ int usb_create_ep_files(struct device *parent, ...@@ -322,8 +324,6 @@ int usb_create_ep_files(struct device *parent,
return retval; return retval;
error_link: error_link:
sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
error_group:
device_unregister(&ep_dev->dev); device_unregister(&ep_dev->dev);
destroy_endpoint_class(); destroy_endpoint_class();
return retval; return retval;
...@@ -348,7 +348,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint) ...@@ -348,7 +348,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
sysfs_remove_link(&ep_dev->dev.parent->kobj, name); sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
device_unregister(&ep_dev->dev); device_unregister(&ep_dev->dev);
endpoint->ep_dev = NULL; endpoint->ep_dev = NULL;
destroy_endpoint_class(); destroy_endpoint_class();
......
...@@ -1607,6 +1607,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1607,6 +1607,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
intf->dev.driver = NULL; intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type; intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type; intf->dev.type = &usb_if_device_type;
intf->dev.groups = usb_interface_groups;
intf->dev.dma_mask = dev->dev.dma_mask; intf->dev.dma_mask = dev->dev.dma_mask;
device_initialize(&intf->dev); device_initialize(&intf->dev);
mark_quiesced(intf); mark_quiesced(intf);
......
...@@ -538,6 +538,46 @@ static struct attribute_group dev_attr_grp = { ...@@ -538,6 +538,46 @@ static struct attribute_group dev_attr_grp = {
.attrs = dev_attrs, .attrs = dev_attrs,
}; };
/* When modifying this list, be sure to modify dev_string_attrs_are_visible()
* accordingly.
*/
static struct attribute *dev_string_attrs[] = {
&dev_attr_manufacturer.attr,
&dev_attr_product.attr,
&dev_attr_serial.attr,
NULL
};
static mode_t dev_string_attrs_are_visible(struct kobject *kobj,
struct attribute *a, int n)
{
struct usb_device *udev = to_usb_device(
container_of(kobj, struct device, kobj));
if (a == &dev_attr_manufacturer.attr) {
if (udev->manufacturer == NULL)
return 0;
} else if (a == &dev_attr_product.attr) {
if (udev->product == NULL)
return 0;
} else if (a == &dev_attr_serial.attr) {
if (udev->serial == NULL)
return 0;
}
return a->mode;
}
static struct attribute_group dev_string_attr_grp = {
.attrs = dev_string_attrs,
.is_visible = dev_string_attrs_are_visible,
};
struct attribute_group *usb_device_groups[] = {
&dev_attr_grp,
&dev_string_attr_grp,
NULL
};
/* Binary descriptors */ /* Binary descriptors */
static ssize_t static ssize_t
...@@ -591,10 +631,9 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) ...@@ -591,10 +631,9 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
struct device *dev = &udev->dev; struct device *dev = &udev->dev;
int retval; int retval;
retval = sysfs_create_group(&dev->kobj, &dev_attr_grp); /* Unforunately these attributes cannot be created before
if (retval) * the uevent is broadcast.
return retval; */
retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); retval = device_create_bin_file(dev, &dev_bin_attr_descriptors);
if (retval) if (retval)
goto error; goto error;
...@@ -607,21 +646,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) ...@@ -607,21 +646,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
if (retval) if (retval)
goto error; goto error;
if (udev->manufacturer) {
retval = device_create_file(dev, &dev_attr_manufacturer);
if (retval)
goto error;
}
if (udev->product) {
retval = device_create_file(dev, &dev_attr_product);
if (retval)
goto error;
}
if (udev->serial) {
retval = device_create_file(dev, &dev_attr_serial);
if (retval)
goto error;
}
retval = usb_create_ep_files(dev, &udev->ep0, udev); retval = usb_create_ep_files(dev, &udev->ep0, udev);
if (retval) if (retval)
goto error; goto error;
...@@ -636,13 +660,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) ...@@ -636,13 +660,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
struct device *dev = &udev->dev; struct device *dev = &udev->dev;
usb_remove_ep_files(&udev->ep0); usb_remove_ep_files(&udev->ep0);
device_remove_file(dev, &dev_attr_manufacturer);
device_remove_file(dev, &dev_attr_product);
device_remove_file(dev, &dev_attr_serial);
remove_power_attributes(dev); remove_power_attributes(dev);
remove_persist_attributes(dev); remove_persist_attributes(dev);
device_remove_bin_file(dev, &dev_bin_attr_descriptors); device_remove_bin_file(dev, &dev_bin_attr_descriptors);
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
} }
/* Interface Accociation Descriptor fields */ /* Interface Accociation Descriptor fields */
...@@ -688,17 +708,15 @@ static ssize_t show_interface_string(struct device *dev, ...@@ -688,17 +708,15 @@ static ssize_t show_interface_string(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_interface *intf; struct usb_interface *intf;
struct usb_device *udev; char *string;
int len;
intf = to_usb_interface(dev); intf = to_usb_interface(dev);
udev = interface_to_usbdev(intf); string = intf->cur_altsetting->string;
len = snprintf(buf, 256, "%s", intf->cur_altsetting->string); barrier(); /* The altsetting might change! */
if (len < 0)
if (!string)
return 0; return 0;
buf[len] = '\n'; return sprintf(buf, "%s\n", string);
buf[len+1] = 0;
return len+1;
} }
static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
...@@ -727,18 +745,6 @@ static ssize_t show_modalias(struct device *dev, ...@@ -727,18 +745,6 @@ static ssize_t show_modalias(struct device *dev,
} }
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
static struct attribute *intf_assoc_attrs[] = {
&dev_attr_iad_bFirstInterface.attr,
&dev_attr_iad_bInterfaceCount.attr,
&dev_attr_iad_bFunctionClass.attr,
&dev_attr_iad_bFunctionSubClass.attr,
&dev_attr_iad_bFunctionProtocol.attr,
NULL,
};
static struct attribute_group intf_assoc_attr_grp = {
.attrs = intf_assoc_attrs,
};
static struct attribute *intf_attrs[] = { static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr, &dev_attr_bInterfaceNumber.attr,
&dev_attr_bAlternateSetting.attr, &dev_attr_bAlternateSetting.attr,
...@@ -753,6 +759,37 @@ static struct attribute_group intf_attr_grp = { ...@@ -753,6 +759,37 @@ static struct attribute_group intf_attr_grp = {
.attrs = intf_attrs, .attrs = intf_attrs,
}; };
static struct attribute *intf_assoc_attrs[] = {
&dev_attr_iad_bFirstInterface.attr,
&dev_attr_iad_bInterfaceCount.attr,
&dev_attr_iad_bFunctionClass.attr,
&dev_attr_iad_bFunctionSubClass.attr,
&dev_attr_iad_bFunctionProtocol.attr,
NULL,
};
static mode_t intf_assoc_attrs_are_visible(struct kobject *kobj,
struct attribute *a, int n)
{
struct usb_interface *intf = to_usb_interface(
container_of(kobj, struct device, kobj));
if (intf->intf_assoc == NULL)
return 0;
return a->mode;
}
static struct attribute_group intf_assoc_attr_grp = {
.attrs = intf_assoc_attrs,
.is_visible = intf_assoc_attrs_are_visible,
};
struct attribute_group *usb_interface_groups[] = {
&intf_attr_grp,
&intf_assoc_attr_grp,
NULL
};
static inline void usb_create_intf_ep_files(struct usb_interface *intf, static inline void usb_create_intf_ep_files(struct usb_interface *intf,
struct usb_device *udev) struct usb_device *udev)
{ {
...@@ -777,23 +814,21 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) ...@@ -777,23 +814,21 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
int usb_create_sysfs_intf_files(struct usb_interface *intf) int usb_create_sysfs_intf_files(struct usb_interface *intf)
{ {
struct device *dev = &intf->dev;
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *alt = intf->cur_altsetting; struct usb_host_interface *alt = intf->cur_altsetting;
int retval; int retval;
if (intf->sysfs_files_created) if (intf->sysfs_files_created)
return 0; return 0;
retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
if (retval)
return retval;
/* The interface string may be present in some altsettings
* and missing in others. Hence its attribute cannot be created
* before the uevent is broadcast.
*/
if (alt->string == NULL) if (alt->string == NULL)
alt->string = usb_cache_string(udev, alt->desc.iInterface); alt->string = usb_cache_string(udev, alt->desc.iInterface);
if (alt->string) if (alt->string)
retval = device_create_file(dev, &dev_attr_interface); retval = device_create_file(&intf->dev, &dev_attr_interface);
if (intf->intf_assoc)
retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
usb_create_intf_ep_files(intf, udev); usb_create_intf_ep_files(intf, udev);
intf->sysfs_files_created = 1; intf->sysfs_files_created = 1;
return 0; return 0;
...@@ -807,7 +842,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf) ...@@ -807,7 +842,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
return; return;
usb_remove_intf_ep_files(intf); usb_remove_intf_ep_files(intf);
device_remove_file(dev, &dev_attr_interface); device_remove_file(dev, &dev_attr_interface);
sysfs_remove_group(&dev->kobj, &intf_attr_grp);
sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
intf->sysfs_files_created = 0; intf->sysfs_files_created = 0;
} }
...@@ -291,6 +291,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, ...@@ -291,6 +291,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
device_initialize(&dev->dev); device_initialize(&dev->dev);
dev->dev.bus = &usb_bus_type; dev->dev.bus = &usb_bus_type;
dev->dev.type = &usb_device_type; dev->dev.type = &usb_device_type;
dev->dev.groups = usb_device_groups;
dev->dev.dma_mask = bus->controller->dma_mask; dev->dev.dma_mask = bus->controller->dma_mask;
set_dev_node(&dev->dev, dev_to_node(bus->controller)); set_dev_node(&dev->dev, dev_to_node(bus->controller));
dev->state = USB_STATE_ATTACHED; dev->state = USB_STATE_ATTACHED;
......
...@@ -130,6 +130,10 @@ static inline int is_active(const struct usb_interface *f) ...@@ -130,6 +130,10 @@ static inline int is_active(const struct usb_interface *f)
/* for labeling diagnostics */ /* for labeling diagnostics */
extern const char *usbcore_name; extern const char *usbcore_name;
/* sysfs stuff */
extern struct attribute_group *usb_device_groups[];
extern struct attribute_group *usb_interface_groups[];
/* usbfs stuff */ /* usbfs stuff */
extern struct mutex usbfs_mutex; extern struct mutex usbfs_mutex;
extern struct usb_driver usbfs_driver; extern struct usb_driver usbfs_driver;
......
...@@ -3251,7 +3251,7 @@ static int udc_pci_probe( ...@@ -3251,7 +3251,7 @@ static int udc_pci_probe(
/* pci setup */ /* pci setup */
if (pci_enable_device(pdev) < 0) { if (pci_enable_device(pdev) < 0) {
kfree(dev); kfree(dev);
dev = 0; dev = NULL;
retval = -ENODEV; retval = -ENODEV;
goto finished; goto finished;
} }
...@@ -3264,7 +3264,7 @@ static int udc_pci_probe( ...@@ -3264,7 +3264,7 @@ static int udc_pci_probe(
if (!request_mem_region(resource, len, name)) { if (!request_mem_region(resource, len, name)) {
dev_dbg(&pdev->dev, "pci device used already\n"); dev_dbg(&pdev->dev, "pci device used already\n");
kfree(dev); kfree(dev);
dev = 0; dev = NULL;
retval = -EBUSY; retval = -EBUSY;
goto finished; goto finished;
} }
...@@ -3274,7 +3274,7 @@ static int udc_pci_probe( ...@@ -3274,7 +3274,7 @@ static int udc_pci_probe(
if (dev->virt_addr == NULL) { if (dev->virt_addr == NULL) {
dev_dbg(&pdev->dev, "start address cannot be mapped\n"); dev_dbg(&pdev->dev, "start address cannot be mapped\n");
kfree(dev); kfree(dev);
dev = 0; dev = NULL;
retval = -EFAULT; retval = -EFAULT;
goto finished; goto finished;
} }
...@@ -3282,7 +3282,7 @@ static int udc_pci_probe( ...@@ -3282,7 +3282,7 @@ static int udc_pci_probe(
if (!pdev->irq) { if (!pdev->irq) {
dev_err(&dev->pdev->dev, "irq not set\n"); dev_err(&dev->pdev->dev, "irq not set\n");
kfree(dev); kfree(dev);
dev = 0; dev = NULL;
retval = -ENODEV; retval = -ENODEV;
goto finished; goto finished;
} }
...@@ -3290,7 +3290,7 @@ static int udc_pci_probe( ...@@ -3290,7 +3290,7 @@ static int udc_pci_probe(
if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
kfree(dev); kfree(dev);
dev = 0; dev = NULL;
retval = -EBUSY; retval = -EBUSY;
goto finished; goto finished;
} }
......
...@@ -649,7 +649,13 @@ static int usba_ep_disable(struct usb_ep *_ep) ...@@ -649,7 +649,13 @@ static int usba_ep_disable(struct usb_ep *_ep)
if (!ep->desc) { if (!ep->desc) {
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name); /* REVISIT because this driver disables endpoints in
* reset_all_endpoints() before calling disconnect(),
* most gadget drivers would trigger this non-error ...
*/
if (udc->gadget.speed != USB_SPEED_UNKNOWN)
DBG(DBG_ERR, "ep_disable: %s not enabled\n",
ep->ep.name);
return -EINVAL; return -EINVAL;
} }
ep->desc = NULL; ep->desc = NULL;
...@@ -1032,8 +1038,6 @@ static struct usba_udc the_udc = { ...@@ -1032,8 +1038,6 @@ static struct usba_udc the_udc = {
.release = nop_release, .release = nop_release,
}, },
}, },
.lock = SPIN_LOCK_UNLOCKED,
}; };
/* /*
...@@ -1052,6 +1056,12 @@ static void reset_all_endpoints(struct usba_udc *udc) ...@@ -1052,6 +1056,12 @@ static void reset_all_endpoints(struct usba_udc *udc)
request_complete(ep, req, -ECONNRESET); request_complete(ep, req, -ECONNRESET);
} }
/* NOTE: normally, the next call to the gadget driver is in
* charge of disabling endpoints... usually disconnect().
* The exception would be entering a high speed test mode.
*
* FIXME remove this code ... and retest thoroughly.
*/
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
if (ep->desc) { if (ep->desc) {
spin_unlock(&udc->lock); spin_unlock(&udc->lock);
...@@ -1219,7 +1229,7 @@ static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) ...@@ -1219,7 +1229,7 @@ static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
struct usb_ctrlrequest *crq) struct usb_ctrlrequest *crq)
{ {
int retval = 0;; int retval = 0;
switch (crq->bRequest) { switch (crq->bRequest) {
case USB_REQ_GET_STATUS: { case USB_REQ_GET_STATUS: {
...@@ -1693,6 +1703,14 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) ...@@ -1693,6 +1703,14 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
usba_writel(udc, INT_CLR, USBA_END_OF_RESET); usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
reset_all_endpoints(udc); reset_all_endpoints(udc);
if (udc->gadget.speed != USB_SPEED_UNKNOWN
&& udc->driver->disconnect) {
udc->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock(&udc->lock);
udc->driver->disconnect(&udc->gadget);
spin_lock(&udc->lock);
}
if (status & USBA_HIGH_SPEED) { if (status & USBA_HIGH_SPEED) {
DBG(DBG_BUS, "High-speed bus reset detected\n"); DBG(DBG_BUS, "High-speed bus reset detected\n");
udc->gadget.speed = USB_SPEED_HIGH; udc->gadget.speed = USB_SPEED_HIGH;
...@@ -1716,9 +1734,13 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) ...@@ -1716,9 +1734,13 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
| USBA_DET_SUSPEND | USBA_DET_SUSPEND
| USBA_END_OF_RESUME)); | USBA_END_OF_RESUME));
/*
* Unclear why we hit this irregularly, e.g. in usbtest,
* but it's clearly harmless...
*/
if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED))
dev_warn(&udc->pdev->dev, dev_dbg(&udc->pdev->dev,
"WARNING: EP0 configuration is invalid!\n"); "ODD: EP0 configuration is invalid!\n");
} }
spin_unlock(&udc->lock); spin_unlock(&udc->lock);
...@@ -1751,9 +1773,11 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) ...@@ -1751,9 +1773,11 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
reset_all_endpoints(udc); reset_all_endpoints(udc);
toggle_bias(0); toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK); usba_writel(udc, CTRL, USBA_DISABLE_MASK);
spin_unlock(&udc->lock); if (udc->driver->disconnect) {
udc->driver->disconnect(&udc->gadget); spin_unlock(&udc->lock);
spin_lock(&udc->lock); udc->driver->disconnect(&udc->gadget);
spin_lock(&udc->lock);
}
} }
udc->vbus_prev = vbus; udc->vbus_prev = vbus;
} }
...@@ -1825,7 +1849,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ...@@ -1825,7 +1849,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!udc->pdev) if (!udc->pdev)
return -ENODEV; return -ENODEV;
if (driver != udc->driver) if (driver != udc->driver || !driver->unbind)
return -EINVAL; return -EINVAL;
if (udc->vbus_pin != -1) if (udc->vbus_pin != -1)
...@@ -1840,6 +1864,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ...@@ -1840,6 +1864,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
toggle_bias(0); toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK); usba_writel(udc, CTRL, USBA_DISABLE_MASK);
if (udc->driver->disconnect)
udc->driver->disconnect(&udc->gadget);
driver->unbind(&udc->gadget); driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL; udc->gadget.dev.driver = NULL;
udc->driver = NULL; udc->driver = NULL;
...@@ -1879,6 +1906,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) ...@@ -1879,6 +1906,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
goto err_get_hclk; goto err_get_hclk;
} }
spin_lock_init(&udc->lock);
udc->pdev = pdev; udc->pdev = pdev;
udc->pclk = pclk; udc->pclk = pclk;
udc->hclk = hclk; udc->hclk = hclk;
......
...@@ -1546,7 +1546,6 @@ static __init void udc_init_data(struct pxa_udc *dev) ...@@ -1546,7 +1546,6 @@ static __init void udc_init_data(struct pxa_udc *dev)
INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0]; dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
ep0_idle(dev); ep0_idle(dev);
strcpy(dev->dev->bus_id, "");
/* PXA endpoints init */ /* PXA endpoints init */
for (i = 0; i < NR_PXA_ENDPOINTS; i++) { for (i = 0; i < NR_PXA_ENDPOINTS; i++) {
...@@ -1746,13 +1745,10 @@ static void handle_ep0_ctrl_req(struct pxa_udc *udc, ...@@ -1746,13 +1745,10 @@ static void handle_ep0_ctrl_req(struct pxa_udc *udc,
ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i); ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i);
} }
le16_to_cpus(&u.r.wValue);
le16_to_cpus(&u.r.wIndex);
le16_to_cpus(&u.r.wLength);
ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n", ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n",
u.r.bRequestType, u.r.bRequest, u.r.bRequestType, u.r.bRequest,
u.r.wValue, u.r.wIndex, u.r.wLength); le16_to_cpu(u.r.wValue), le16_to_cpu(u.r.wIndex),
le16_to_cpu(u.r.wLength));
if (unlikely(have_extrabytes)) if (unlikely(have_extrabytes))
goto stall; goto stall;
...@@ -2296,7 +2292,8 @@ static void pxa_udc_shutdown(struct platform_device *_dev) ...@@ -2296,7 +2292,8 @@ static void pxa_udc_shutdown(struct platform_device *_dev)
{ {
struct pxa_udc *udc = platform_get_drvdata(_dev); struct pxa_udc *udc = platform_get_drvdata(_dev);
udc_disable(udc); if (udc_readl(udc, UDCCR) & UDCCR_UDE)
udc_disable(udc);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -2361,9 +2358,8 @@ static int pxa_udc_resume(struct platform_device *_dev) ...@@ -2361,9 +2358,8 @@ static int pxa_udc_resume(struct platform_device *_dev)
* Upon exit from sleep mode and before clearing OTGPH, * Upon exit from sleep mode and before clearing OTGPH,
* Software must configure the USB OTG pad, UDC, and UHC * Software must configure the USB OTG pad, UDC, and UHC
* to the state they were in before entering sleep mode. * to the state they were in before entering sleep mode.
*
* Should be : PSSR |= PSSR_OTGPH;
*/ */
PSSR |= PSSR_OTGPH;
return 0; return 0;
} }
...@@ -2387,6 +2383,9 @@ static struct platform_driver udc_driver = { ...@@ -2387,6 +2383,9 @@ static struct platform_driver udc_driver = {
static int __init udc_init(void) static int __init udc_init(void)
{ {
if (!cpu_is_pxa27x())
return -ENODEV;
printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
return platform_driver_probe(&udc_driver, pxa_udc_probe); return platform_driver_probe(&udc_driver, pxa_udc_probe);
} }
......
...@@ -484,4 +484,12 @@ static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget) ...@@ -484,4 +484,12 @@ static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
#define ep_warn(ep, fmt, arg...) \ #define ep_warn(ep, fmt, arg...) \
dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg) dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
/*
* Cannot include pxa-regs.h, as register names are similar.
* So PSSR is redefined here. This should be removed once UDC registers will
* be gone from pxa-regs.h.
*/
#define PSSR __REG(0x40F00004) /* Power Manager Sleep Status */
#define PSSR_OTGPH (1 << 6) /* OTG Peripheral Hold */
#endif /* __LINUX_USB_GADGET_PXA27X_H */ #endif /* __LINUX_USB_GADGET_PXA27X_H */
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
* This software is distributed under the terms of the GNU General * This software is distributed under the terms of the GNU General
* Public License ("GPL") as published by the Free Software Foundation, * Public License ("GPL") as published by the Free Software Foundation,
* either version 2 of that License or (at your option) any later version. * either version 2 of that License or (at your option) any later version.
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -33,7 +32,7 @@ ...@@ -33,7 +32,7 @@
/* Defines */ /* Defines */
#define GS_VERSION_STR "v2.2" #define GS_VERSION_STR "v2.2"
#define GS_VERSION_NUM 0x0202 #define GS_VERSION_NUM 0x2200
#define GS_LONG_NAME "Gadget Serial" #define GS_LONG_NAME "Gadget Serial"
#define GS_SHORT_NAME "g_serial" #define GS_SHORT_NAME "g_serial"
...@@ -41,7 +40,11 @@ ...@@ -41,7 +40,11 @@
#define GS_MAJOR 127 #define GS_MAJOR 127
#define GS_MINOR_START 0 #define GS_MINOR_START 0
#define GS_NUM_PORTS 16 /* REVISIT only one port is supported for now;
* see gs_{send,recv}_packet() ... no multiplexing,
* and no support for multiple ACM devices.
*/
#define GS_NUM_PORTS 1
#define GS_NUM_CONFIGS 1 #define GS_NUM_CONFIGS 1
#define GS_NO_CONFIG_ID 0 #define GS_NO_CONFIG_ID 0
...@@ -65,6 +68,9 @@ ...@@ -65,6 +68,9 @@
#define GS_DEFAULT_USE_ACM 0 #define GS_DEFAULT_USE_ACM 0
/* 9600-8-N-1 ... matches init_termios.c_cflag and defaults
* expected by "usbser.sys" on MS-Windows.
*/
#define GS_DEFAULT_DTE_RATE 9600 #define GS_DEFAULT_DTE_RATE 9600
#define GS_DEFAULT_DATA_BITS 8 #define GS_DEFAULT_DATA_BITS 8
#define GS_DEFAULT_PARITY USB_CDC_NO_PARITY #define GS_DEFAULT_PARITY USB_CDC_NO_PARITY
...@@ -107,10 +113,6 @@ static int debug = 1; ...@@ -107,10 +113,6 @@ static int debug = 1;
#define GS_NOTIFY_MAXPACKET 8 #define GS_NOTIFY_MAXPACKET 8
/* Structures */
struct gs_dev;
/* circular buffer */ /* circular buffer */
struct gs_buf { struct gs_buf {
unsigned int buf_size; unsigned int buf_size;
...@@ -119,12 +121,6 @@ struct gs_buf { ...@@ -119,12 +121,6 @@ struct gs_buf {
char *buf_put; char *buf_put;
}; };
/* list of requests */
struct gs_req_entry {
struct list_head re_entry;
struct usb_request *re_req;
};
/* the port structure holds info for each port, one for each minor number */ /* the port structure holds info for each port, one for each minor number */
struct gs_port { struct gs_port {
struct gs_dev *port_dev; /* pointer to device struct */ struct gs_dev *port_dev; /* pointer to device struct */
...@@ -164,26 +160,7 @@ struct gs_dev { ...@@ -164,26 +160,7 @@ struct gs_dev {
/* Functions */ /* Functions */
/* module */ /* tty driver internals */
static int __init gs_module_init(void);
static void __exit gs_module_exit(void);
/* tty driver */
static int gs_open(struct tty_struct *tty, struct file *file);
static void gs_close(struct tty_struct *tty, struct file *file);
static int gs_write(struct tty_struct *tty,
const unsigned char *buf, int count);
static int gs_put_char(struct tty_struct *tty, unsigned char ch);
static void gs_flush_chars(struct tty_struct *tty);
static int gs_write_room(struct tty_struct *tty);
static int gs_chars_in_buffer(struct tty_struct *tty);
static void gs_throttle(struct tty_struct * tty);
static void gs_unthrottle(struct tty_struct * tty);
static void gs_break(struct tty_struct *tty, int break_state);
static int gs_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static void gs_set_termios(struct tty_struct *tty, struct ktermios *old);
static int gs_send(struct gs_dev *dev); static int gs_send(struct gs_dev *dev);
static int gs_send_packet(struct gs_dev *dev, char *packet, static int gs_send_packet(struct gs_dev *dev, char *packet,
unsigned int size); unsigned int size);
...@@ -192,19 +169,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, ...@@ -192,19 +169,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet,
static void gs_read_complete(struct usb_ep *ep, struct usb_request *req); static void gs_read_complete(struct usb_ep *ep, struct usb_request *req);
static void gs_write_complete(struct usb_ep *ep, struct usb_request *req); static void gs_write_complete(struct usb_ep *ep, struct usb_request *req);
/* gadget driver */ /* gadget driver internals */
static int gs_bind(struct usb_gadget *gadget);
static void gs_unbind(struct usb_gadget *gadget);
static int gs_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
static int gs_setup_standard(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
static int gs_setup_class(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req);
static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
struct usb_request *req);
static void gs_disconnect(struct usb_gadget *gadget);
static int gs_set_config(struct gs_dev *dev, unsigned config); static int gs_set_config(struct gs_dev *dev, unsigned config);
static void gs_reset_config(struct gs_dev *dev); static void gs_reset_config(struct gs_dev *dev);
static int gs_build_config_buf(u8 *buf, struct usb_gadget *g, static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
...@@ -214,10 +179,6 @@ static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, ...@@ -214,10 +179,6 @@ static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
gfp_t kmalloc_flags); gfp_t kmalloc_flags);
static void gs_free_req(struct usb_ep *ep, struct usb_request *req); static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,
gfp_t kmalloc_flags);
static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);
static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags); static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
static void gs_free_ports(struct gs_dev *dev); static void gs_free_ports(struct gs_dev *dev);
...@@ -232,62 +193,15 @@ static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, ...@@ -232,62 +193,15 @@ static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf,
static unsigned int gs_buf_get(struct gs_buf *gb, char *buf, static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,
unsigned int count); unsigned int count);
/* external functions */
extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode);
/* Globals */ /* Globals */
static struct gs_dev *gs_device; static struct gs_dev *gs_device;
static const char *EP_IN_NAME;
static const char *EP_OUT_NAME;
static const char *EP_NOTIFY_NAME;
static struct mutex gs_open_close_lock[GS_NUM_PORTS]; static struct mutex gs_open_close_lock[GS_NUM_PORTS];
static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE;
static unsigned int use_acm = GS_DEFAULT_USE_ACM;
/* tty driver struct */
static const struct tty_operations gs_tty_ops = {
.open = gs_open,
.close = gs_close,
.write = gs_write,
.put_char = gs_put_char,
.flush_chars = gs_flush_chars,
.write_room = gs_write_room,
.ioctl = gs_ioctl,
.set_termios = gs_set_termios,
.throttle = gs_throttle,
.unthrottle = gs_unthrottle,
.break_ctl = gs_break,
.chars_in_buffer = gs_chars_in_buffer,
};
static struct tty_driver *gs_tty_driver;
/* gadget driver struct */
static struct usb_gadget_driver gs_gadget_driver = {
#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
#else
.speed = USB_SPEED_FULL,
#endif /* CONFIG_USB_GADGET_DUALSPEED */
.function = GS_LONG_NAME,
.bind = gs_bind,
.unbind = gs_unbind,
.setup = gs_setup,
.disconnect = gs_disconnect,
.driver = {
.name = GS_SHORT_NAME,
},
};
/*-------------------------------------------------------------------------*/
/* USB descriptors */ /* USB descriptors */
...@@ -304,7 +218,6 @@ static char manufacturer[50]; ...@@ -304,7 +218,6 @@ static char manufacturer[50];
static struct usb_string gs_strings[] = { static struct usb_string gs_strings[] = {
{ GS_MANUFACTURER_STR_ID, manufacturer }, { GS_MANUFACTURER_STR_ID, manufacturer },
{ GS_PRODUCT_STR_ID, GS_LONG_NAME }, { GS_PRODUCT_STR_ID, GS_LONG_NAME },
{ GS_SERIAL_STR_ID, "0" },
{ GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" }, { GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" },
{ GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" }, { GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" },
{ GS_CONTROL_STR_ID, "Gadget Serial Control" }, { GS_CONTROL_STR_ID, "Gadget Serial Control" },
...@@ -327,7 +240,6 @@ static struct usb_device_descriptor gs_device_desc = { ...@@ -327,7 +240,6 @@ static struct usb_device_descriptor gs_device_desc = {
.idProduct = __constant_cpu_to_le16(GS_PRODUCT_ID), .idProduct = __constant_cpu_to_le16(GS_PRODUCT_ID),
.iManufacturer = GS_MANUFACTURER_STR_ID, .iManufacturer = GS_MANUFACTURER_STR_ID,
.iProduct = GS_PRODUCT_STR_ID, .iProduct = GS_PRODUCT_STR_ID,
.iSerialNumber = GS_SERIAL_STR_ID,
.bNumConfigurations = GS_NUM_CONFIGS, .bNumConfigurations = GS_NUM_CONFIGS,
}; };
...@@ -364,7 +276,7 @@ static const struct usb_interface_descriptor gs_bulk_interface_desc = { ...@@ -364,7 +276,7 @@ static const struct usb_interface_descriptor gs_bulk_interface_desc = {
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = GS_BULK_INTERFACE_ID, .bInterfaceNumber = GS_BULK_INTERFACE_ID,
.bNumEndpoints = 2, .bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_CDC_DATA, .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 0, .bInterfaceSubClass = 0,
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
.iInterface = GS_DATA_STR_ID, .iInterface = GS_DATA_STR_ID,
...@@ -521,6 +433,8 @@ static const struct usb_descriptor_header *gs_acm_highspeed_function[] = { ...@@ -521,6 +433,8 @@ static const struct usb_descriptor_header *gs_acm_highspeed_function[] = {
}; };
/*-------------------------------------------------------------------------*/
/* Module */ /* Module */
MODULE_DESCRIPTION(GS_LONG_NAME); MODULE_DESCRIPTION(GS_LONG_NAME);
MODULE_AUTHOR("Al Borchers"); MODULE_AUTHOR("Al Borchers");
...@@ -531,84 +445,23 @@ module_param(debug, int, S_IRUGO|S_IWUSR); ...@@ -531,84 +445,23 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
#endif #endif
static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
module_param(read_q_size, uint, S_IRUGO); module_param(read_q_size, uint, S_IRUGO);
MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32"); MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32");
static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
module_param(write_q_size, uint, S_IRUGO); module_param(write_q_size, uint, S_IRUGO);
MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32"); MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32");
static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE;
module_param(write_buf_size, uint, S_IRUGO); module_param(write_buf_size, uint, S_IRUGO);
MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192"); MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192");
static unsigned int use_acm = GS_DEFAULT_USE_ACM;
module_param(use_acm, uint, S_IRUGO); module_param(use_acm, uint, S_IRUGO);
MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no"); MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no");
module_init(gs_module_init); /*-------------------------------------------------------------------------*/
module_exit(gs_module_exit);
/*
* gs_module_init
*
* Register as a USB gadget driver and a tty driver.
*/
static int __init gs_module_init(void)
{
int i;
int retval;
retval = usb_gadget_register_driver(&gs_gadget_driver);
if (retval) {
pr_err("gs_module_init: cannot register gadget driver, "
"ret=%d\n", retval);
return retval;
}
gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS);
if (!gs_tty_driver)
return -ENOMEM;
gs_tty_driver->owner = THIS_MODULE;
gs_tty_driver->driver_name = GS_SHORT_NAME;
gs_tty_driver->name = "ttygs";
gs_tty_driver->major = GS_MAJOR;
gs_tty_driver->minor_start = GS_MINOR_START;
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
gs_tty_driver->init_termios = tty_std_termios;
gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
tty_set_operations(gs_tty_driver, &gs_tty_ops);
for (i=0; i < GS_NUM_PORTS; i++)
mutex_init(&gs_open_close_lock[i]);
retval = tty_register_driver(gs_tty_driver);
if (retval) {
usb_gadget_unregister_driver(&gs_gadget_driver);
put_tty_driver(gs_tty_driver);
pr_err("gs_module_init: cannot register tty driver, "
"ret=%d\n", retval);
return retval;
}
pr_info("gs_module_init: %s %s loaded\n",
GS_LONG_NAME, GS_VERSION_STR);
return 0;
}
/*
* gs_module_exit
*
* Unregister as a tty driver and a USB gadget driver.
*/
static void __exit gs_module_exit(void)
{
tty_unregister_driver(gs_tty_driver);
put_tty_driver(gs_tty_driver);
usb_gadget_unregister_driver(&gs_gadget_driver);
pr_info("gs_module_exit: %s %s unloaded\n",
GS_LONG_NAME, GS_VERSION_STR);
}
/* TTY Driver */ /* TTY Driver */
...@@ -753,15 +606,15 @@ static int gs_open(struct tty_struct *tty, struct file *file) ...@@ -753,15 +606,15 @@ static int gs_open(struct tty_struct *tty, struct file *file)
* gs_close * gs_close
*/ */
#define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ static int gs_write_finished_event_safely(struct gs_port *p)
({ \ {
int cond; \ int cond;
\
spin_lock_irq(&(p)->port_lock); \ spin_lock_irq(&(p)->port_lock);
cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf);
spin_unlock_irq(&(p)->port_lock); \ spin_unlock_irq(&(p)->port_lock);
cond; \ return cond;
}) }
static void gs_close(struct tty_struct *tty, struct file *file) static void gs_close(struct tty_struct *tty, struct file *file)
{ {
...@@ -807,7 +660,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) ...@@ -807,7 +660,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
if (gs_buf_data_avail(port->port_write_buf) > 0) { if (gs_buf_data_avail(port->port_write_buf) > 0) {
spin_unlock_irq(&port->port_lock); spin_unlock_irq(&port->port_lock);
wait_event_interruptible_timeout(port->port_write_wait, wait_event_interruptible_timeout(port->port_write_wait,
GS_WRITE_FINISHED_EVENT_SAFELY(port), gs_write_finished_event_safely(port),
GS_CLOSE_TIMEOUT * HZ); GS_CLOSE_TIMEOUT * HZ);
spin_lock_irq(&port->port_lock); spin_lock_irq(&port->port_lock);
} }
...@@ -1065,6 +918,23 @@ static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) ...@@ -1065,6 +918,23 @@ static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
{ {
} }
static const struct tty_operations gs_tty_ops = {
.open = gs_open,
.close = gs_close,
.write = gs_write,
.put_char = gs_put_char,
.flush_chars = gs_flush_chars,
.write_room = gs_write_room,
.ioctl = gs_ioctl,
.set_termios = gs_set_termios,
.throttle = gs_throttle,
.unthrottle = gs_unthrottle,
.break_ctl = gs_break,
.chars_in_buffer = gs_chars_in_buffer,
};
/*-------------------------------------------------------------------------*/
/* /*
* gs_send * gs_send
* *
...@@ -1080,7 +950,6 @@ static int gs_send(struct gs_dev *dev) ...@@ -1080,7 +950,6 @@ static int gs_send(struct gs_dev *dev)
unsigned long flags; unsigned long flags;
struct usb_ep *ep; struct usb_ep *ep;
struct usb_request *req; struct usb_request *req;
struct gs_req_entry *req_entry;
if (dev == NULL) { if (dev == NULL) {
pr_err("gs_send: NULL device pointer\n"); pr_err("gs_send: NULL device pointer\n");
...@@ -1093,10 +962,8 @@ static int gs_send(struct gs_dev *dev) ...@@ -1093,10 +962,8 @@ static int gs_send(struct gs_dev *dev)
while(!list_empty(&dev->dev_req_list)) { while(!list_empty(&dev->dev_req_list)) {
req_entry = list_entry(dev->dev_req_list.next, req = list_entry(dev->dev_req_list.next,
struct gs_req_entry, re_entry); struct usb_request, list);
req = req_entry->re_req;
len = gs_send_packet(dev, req->buf, ep->maxpacket); len = gs_send_packet(dev, req->buf, ep->maxpacket);
...@@ -1106,7 +973,7 @@ static int gs_send(struct gs_dev *dev) ...@@ -1106,7 +973,7 @@ static int gs_send(struct gs_dev *dev)
*((unsigned char *)req->buf), *((unsigned char *)req->buf),
*((unsigned char *)req->buf+1), *((unsigned char *)req->buf+1),
*((unsigned char *)req->buf+2)); *((unsigned char *)req->buf+2));
list_del(&req_entry->re_entry); list_del(&req->list);
req->length = len; req->length = len;
spin_unlock_irqrestore(&dev->dev_lock, flags); spin_unlock_irqrestore(&dev->dev_lock, flags);
if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
...@@ -1289,7 +1156,6 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -1289,7 +1156,6 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
{ {
struct gs_dev *dev = ep->driver_data; struct gs_dev *dev = ep->driver_data;
struct gs_req_entry *gs_req = req->context;
if (dev == NULL) { if (dev == NULL) {
pr_err("gs_write_complete: NULL device pointer\n"); pr_err("gs_write_complete: NULL device pointer\n");
...@@ -1300,13 +1166,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -1300,13 +1166,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
case 0: case 0:
/* normal completion */ /* normal completion */
requeue: requeue:
if (gs_req == NULL) {
pr_err("gs_write_complete: NULL request pointer\n");
return;
}
spin_lock(&dev->dev_lock); spin_lock(&dev->dev_lock);
list_add(&gs_req->re_entry, &dev->dev_req_list); list_add(&req->list, &dev->dev_req_list);
spin_unlock(&dev->dev_lock); spin_unlock(&dev->dev_lock);
gs_send(dev); gs_send(dev);
...@@ -1328,8 +1189,38 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -1328,8 +1189,38 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
} }
} }
/*-------------------------------------------------------------------------*/
/* Gadget Driver */ /* Gadget Driver */
/*
* gs_unbind
*
* Called on module unload. Frees the control request and device
* structure.
*/
static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
{
struct gs_dev *dev = get_gadget_data(gadget);
gs_device = NULL;
/* read/write requests already freed, only control request remains */
if (dev != NULL) {
if (dev->dev_ctrl_req != NULL) {
gs_free_req(gadget->ep0, dev->dev_ctrl_req);
dev->dev_ctrl_req = NULL;
}
gs_reset_config(dev);
gs_free_ports(dev);
kfree(dev);
set_gadget_data(gadget, NULL);
}
pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME,
GS_VERSION_STR);
}
/* /*
* gs_bind * gs_bind
* *
...@@ -1362,19 +1253,23 @@ static int __init gs_bind(struct usb_gadget *gadget) ...@@ -1362,19 +1253,23 @@ static int __init gs_bind(struct usb_gadget *gadget)
__constant_cpu_to_le16(GS_VERSION_NUM|0x0099); __constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
} }
dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL);
if (dev == NULL)
return -ENOMEM;
usb_ep_autoconfig_reset(gadget); usb_ep_autoconfig_reset(gadget);
ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc); ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
if (!ep) if (!ep)
goto autoconf_fail; goto autoconf_fail;
EP_IN_NAME = ep->name; dev->dev_in_ep = ep;
ep->driver_data = ep; /* claim the endpoint */ ep->driver_data = dev; /* claim the endpoint */
ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc); ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
if (!ep) if (!ep)
goto autoconf_fail; goto autoconf_fail;
EP_OUT_NAME = ep->name; dev->dev_out_ep = ep;
ep->driver_data = ep; /* claim the endpoint */ ep->driver_data = dev; /* claim the endpoint */
if (use_acm) { if (use_acm) {
ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc); ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
...@@ -1384,8 +1279,8 @@ static int __init gs_bind(struct usb_gadget *gadget) ...@@ -1384,8 +1279,8 @@ static int __init gs_bind(struct usb_gadget *gadget)
} }
gs_device_desc.idProduct = __constant_cpu_to_le16( gs_device_desc.idProduct = __constant_cpu_to_le16(
GS_CDC_PRODUCT_ID), GS_CDC_PRODUCT_ID),
EP_NOTIFY_NAME = ep->name; dev->dev_notify_ep = ep;
ep->driver_data = ep; /* claim the endpoint */ ep->driver_data = dev; /* claim the endpoint */
} }
gs_device_desc.bDeviceClass = use_acm gs_device_desc.bDeviceClass = use_acm
...@@ -1415,9 +1310,7 @@ static int __init gs_bind(struct usb_gadget *gadget) ...@@ -1415,9 +1310,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
} }
gs_device = dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL); gs_device = dev;
if (dev == NULL)
return -ENOMEM;
snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
init_utsname()->sysname, init_utsname()->release, init_utsname()->sysname, init_utsname()->release,
...@@ -1441,8 +1334,6 @@ static int __init gs_bind(struct usb_gadget *gadget) ...@@ -1441,8 +1334,6 @@ static int __init gs_bind(struct usb_gadget *gadget)
gs_unbind(gadget); gs_unbind(gadget);
return -ENOMEM; return -ENOMEM;
} }
dev->dev_ctrl_req->complete = gs_setup_complete;
gadget->ep0->driver_data = dev; gadget->ep0->driver_data = dev;
pr_info("gs_bind: %s %s bound\n", pr_info("gs_bind: %s %s bound\n",
...@@ -1451,99 +1342,11 @@ static int __init gs_bind(struct usb_gadget *gadget) ...@@ -1451,99 +1342,11 @@ static int __init gs_bind(struct usb_gadget *gadget)
return 0; return 0;
autoconf_fail: autoconf_fail:
kfree(dev);
pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name); pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name);
return -ENODEV; return -ENODEV;
} }
/*
* gs_unbind
*
* Called on module unload. Frees the control request and device
* structure.
*/
static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
{
struct gs_dev *dev = get_gadget_data(gadget);
gs_device = NULL;
/* read/write requests already freed, only control request remains */
if (dev != NULL) {
if (dev->dev_ctrl_req != NULL) {
gs_free_req(gadget->ep0, dev->dev_ctrl_req);
dev->dev_ctrl_req = NULL;
}
gs_free_ports(dev);
if (dev->dev_notify_ep)
usb_ep_disable(dev->dev_notify_ep);
if (dev->dev_in_ep)
usb_ep_disable(dev->dev_in_ep);
if (dev->dev_out_ep)
usb_ep_disable(dev->dev_out_ep);
kfree(dev);
set_gadget_data(gadget, NULL);
}
pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME,
GS_VERSION_STR);
}
/*
* gs_setup
*
* Implements all the control endpoint functionality that's not
* handled in hardware or the hardware driver.
*
* Returns the size of the data sent to the host, or a negative
* error number.
*/
static int gs_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl)
{
int ret = -EOPNOTSUPP;
struct gs_dev *dev = get_gadget_data(gadget);
struct usb_request *req = dev->dev_ctrl_req;
u16 wIndex = le16_to_cpu(ctrl->wIndex);
u16 wValue = le16_to_cpu(ctrl->wValue);
u16 wLength = le16_to_cpu(ctrl->wLength);
req->complete = gs_setup_complete;
switch (ctrl->bRequestType & USB_TYPE_MASK) {
case USB_TYPE_STANDARD:
ret = gs_setup_standard(gadget,ctrl);
break;
case USB_TYPE_CLASS:
ret = gs_setup_class(gadget,ctrl);
break;
default:
pr_err("gs_setup: unknown request, type=%02x, request=%02x, "
"value=%04x, index=%04x, length=%d\n",
ctrl->bRequestType, ctrl->bRequest,
wValue, wIndex, wLength);
break;
}
/* respond with data transfer before status phase? */
if (ret >= 0) {
req->length = ret;
req->zero = ret < wLength
&& (ret % gadget->ep0->maxpacket) == 0;
ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
if (ret < 0) {
pr_err("gs_setup: cannot queue response, ret=%d\n",
ret);
req->status = 0;
gs_setup_complete(gadget->ep0, req);
}
}
/* device either stalls (ret < 0) or reports success */
return ret;
}
static int gs_setup_standard(struct usb_gadget *gadget, static int gs_setup_standard(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl) const struct usb_ctrlrequest *ctrl)
{ {
...@@ -1673,6 +1476,42 @@ static int gs_setup_standard(struct usb_gadget *gadget, ...@@ -1673,6 +1476,42 @@ static int gs_setup_standard(struct usb_gadget *gadget,
return ret; return ret;
} }
static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
struct usb_request *req)
{
struct gs_dev *dev = ep->driver_data;
struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
switch (req->status) {
case 0:
/* normal completion */
if (req->actual != sizeof(port->port_line_coding))
usb_ep_set_halt(ep);
else if (port) {
struct usb_cdc_line_coding *value = req->buf;
/* REVISIT: we currently just remember this data.
* If we change that, (a) validate it first, then
* (b) update whatever hardware needs updating.
*/
spin_lock(&port->port_lock);
port->port_line_coding = *value;
spin_unlock(&port->port_lock);
}
break;
case -ESHUTDOWN:
/* disconnect */
gs_free_req(ep, req);
break;
default:
/* unexpected */
break;
}
return;
}
static int gs_setup_class(struct usb_gadget *gadget, static int gs_setup_class(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl) const struct usb_ctrlrequest *ctrl)
{ {
...@@ -1734,52 +1573,72 @@ static int gs_setup_class(struct usb_gadget *gadget, ...@@ -1734,52 +1573,72 @@ static int gs_setup_class(struct usb_gadget *gadget,
return ret; return ret;
} }
static void gs_setup_complete_set_line_coding(struct usb_ep *ep, /*
struct usb_request *req) * gs_setup_complete
*/
static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req)
{ {
struct gs_dev *dev = ep->driver_data; if (req->status || req->actual != req->length) {
struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ pr_err("gs_setup_complete: status error, status=%d, "
"actual=%d, length=%d\n",
req->status, req->actual, req->length);
}
}
switch (req->status) { /*
case 0: * gs_setup
/* normal completion */ *
if (req->actual != sizeof(port->port_line_coding)) * Implements all the control endpoint functionality that's not
usb_ep_set_halt(ep); * handled in hardware or the hardware driver.
else if (port) { *
struct usb_cdc_line_coding *value = req->buf; * Returns the size of the data sent to the host, or a negative
* error number.
*/
static int gs_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl)
{
int ret = -EOPNOTSUPP;
struct gs_dev *dev = get_gadget_data(gadget);
struct usb_request *req = dev->dev_ctrl_req;
u16 wIndex = le16_to_cpu(ctrl->wIndex);
u16 wValue = le16_to_cpu(ctrl->wValue);
u16 wLength = le16_to_cpu(ctrl->wLength);
/* REVISIT: we currently just remember this data. req->complete = gs_setup_complete;
* If we change that, (a) validate it first, then
* (b) update whatever hardware needs updating. switch (ctrl->bRequestType & USB_TYPE_MASK) {
*/ case USB_TYPE_STANDARD:
spin_lock(&port->port_lock); ret = gs_setup_standard(gadget, ctrl);
port->port_line_coding = *value;
spin_unlock(&port->port_lock);
}
break; break;
case -ESHUTDOWN: case USB_TYPE_CLASS:
/* disconnect */ ret = gs_setup_class(gadget, ctrl);
gs_free_req(ep, req);
break; break;
default: default:
/* unexpected */ pr_err("gs_setup: unknown request, type=%02x, request=%02x, "
"value=%04x, index=%04x, length=%d\n",
ctrl->bRequestType, ctrl->bRequest,
wValue, wIndex, wLength);
break; break;
} }
return;
}
/* /* respond with data transfer before status phase? */
* gs_setup_complete if (ret >= 0) {
*/ req->length = ret;
static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req) req->zero = ret < wLength
{ && (ret % gadget->ep0->maxpacket) == 0;
if (req->status || req->actual != req->length) { ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
pr_err("gs_setup_complete: status error, status=%d, " if (ret < 0) {
"actual=%d, length=%d\n", pr_err("gs_setup: cannot queue response, ret=%d\n",
req->status, req->actual, req->length); ret);
req->status = 0;
gs_setup_complete(gadget->ep0, req);
}
} }
/* device either stalls (ret < 0) or reports success */
return ret;
} }
/* /*
...@@ -1811,6 +1670,23 @@ static void gs_disconnect(struct usb_gadget *gadget) ...@@ -1811,6 +1670,23 @@ static void gs_disconnect(struct usb_gadget *gadget)
pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME); pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME);
} }
static struct usb_gadget_driver gs_gadget_driver = {
#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
#else
.speed = USB_SPEED_FULL,
#endif /* CONFIG_USB_GADGET_DUALSPEED */
.function = GS_LONG_NAME,
.bind = gs_bind,
.unbind = gs_unbind,
.setup = gs_setup,
.disconnect = gs_disconnect,
.driver = {
.name = GS_SHORT_NAME,
.owner = THIS_MODULE,
},
};
/* /*
* gs_set_config * gs_set_config
* *
...@@ -1826,9 +1702,8 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) ...@@ -1826,9 +1702,8 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
int ret = 0; int ret = 0;
struct usb_gadget *gadget = dev->dev_gadget; struct usb_gadget *gadget = dev->dev_gadget;
struct usb_ep *ep; struct usb_ep *ep;
struct usb_endpoint_descriptor *ep_desc; struct usb_endpoint_descriptor *out, *in, *notify;
struct usb_request *req; struct usb_request *req;
struct gs_req_entry *req_entry;
if (dev == NULL) { if (dev == NULL) {
pr_err("gs_set_config: NULL device pointer\n"); pr_err("gs_set_config: NULL device pointer\n");
...@@ -1846,86 +1721,62 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) ...@@ -1846,86 +1721,62 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
case GS_BULK_CONFIG_ID: case GS_BULK_CONFIG_ID:
if (use_acm) if (use_acm)
return -EINVAL; return -EINVAL;
/* device specific optimizations */
if (gadget_is_net2280(gadget))
net2280_set_fifo_mode(gadget, 1);
break; break;
case GS_ACM_CONFIG_ID: case GS_ACM_CONFIG_ID:
if (!use_acm) if (!use_acm)
return -EINVAL; return -EINVAL;
/* device specific optimizations */
if (gadget_is_net2280(gadget))
net2280_set_fifo_mode(gadget, 1);
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
dev->dev_config = config; in = choose_ep_desc(gadget,
&gs_highspeed_in_desc,
gadget_for_each_ep(ep, gadget) { &gs_fullspeed_in_desc);
out = choose_ep_desc(gadget,
if (EP_NOTIFY_NAME &gs_highspeed_out_desc,
&& strcmp(ep->name, EP_NOTIFY_NAME) == 0) { &gs_fullspeed_out_desc);
ep_desc = choose_ep_desc(gadget, notify = dev->dev_notify_ep
? choose_ep_desc(gadget,
&gs_highspeed_notify_desc, &gs_highspeed_notify_desc,
&gs_fullspeed_notify_desc); &gs_fullspeed_notify_desc)
ret = usb_ep_enable(ep,ep_desc); : NULL;
if (ret == 0) {
ep->driver_data = dev;
dev->dev_notify_ep = ep;
dev->dev_notify_ep_desc = ep_desc;
} else {
pr_err("gs_set_config: cannot enable NOTIFY "
"endpoint %s, ret=%d\n",
ep->name, ret);
goto exit_reset_config;
}
}
else if (strcmp(ep->name, EP_IN_NAME) == 0) {
ep_desc = choose_ep_desc(gadget,
&gs_highspeed_in_desc,
&gs_fullspeed_in_desc);
ret = usb_ep_enable(ep,ep_desc);
if (ret == 0) {
ep->driver_data = dev;
dev->dev_in_ep = ep;
dev->dev_in_ep_desc = ep_desc;
} else {
pr_err("gs_set_config: cannot enable IN "
"endpoint %s, ret=%d\n",
ep->name, ret);
goto exit_reset_config;
}
}
else if (strcmp(ep->name, EP_OUT_NAME) == 0) { ret = usb_ep_enable(dev->dev_in_ep, in);
ep_desc = choose_ep_desc(gadget, if (ret == 0) {
&gs_highspeed_out_desc, dev->dev_in_ep_desc = in;
&gs_fullspeed_out_desc); } else {
ret = usb_ep_enable(ep,ep_desc); pr_debug("%s: cannot enable %s %s, ret=%d\n",
if (ret == 0) { __func__, "IN", dev->dev_in_ep->name, ret);
ep->driver_data = dev; return ret;
dev->dev_out_ep = ep; }
dev->dev_out_ep_desc = ep_desc;
} else {
pr_err("gs_set_config: cannot enable OUT "
"endpoint %s, ret=%d\n",
ep->name, ret);
goto exit_reset_config;
}
}
ret = usb_ep_enable(dev->dev_out_ep, out);
if (ret == 0) {
dev->dev_out_ep_desc = out;
} else {
pr_debug("%s: cannot enable %s %s, ret=%d\n",
__func__, "OUT", dev->dev_out_ep->name, ret);
fail0:
usb_ep_disable(dev->dev_in_ep);
return ret;
} }
if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL if (notify) {
|| (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) { ret = usb_ep_enable(dev->dev_notify_ep, notify);
pr_err("gs_set_config: cannot find endpoints\n"); if (ret == 0) {
ret = -ENODEV; dev->dev_notify_ep_desc = notify;
goto exit_reset_config; } else {
pr_debug("%s: cannot enable %s %s, ret=%d\n",
__func__, "NOTIFY",
dev->dev_notify_ep->name, ret);
usb_ep_disable(dev->dev_out_ep);
goto fail0;
}
} }
dev->dev_config = config;
/* allocate and queue read requests */ /* allocate and queue read requests */
ep = dev->dev_out_ep; ep = dev->dev_out_ep;
for (i=0; i<read_q_size && ret == 0; i++) { for (i=0; i<read_q_size && ret == 0; i++) {
...@@ -1946,9 +1797,10 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) ...@@ -1946,9 +1797,10 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
/* allocate write requests, and put on free list */ /* allocate write requests, and put on free list */
ep = dev->dev_in_ep; ep = dev->dev_in_ep;
for (i=0; i<write_q_size; i++) { for (i=0; i<write_q_size; i++) {
if ((req_entry=gs_alloc_req_entry(ep, ep->maxpacket, GFP_ATOMIC))) { req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
req_entry->re_req->complete = gs_write_complete; if (req) {
list_add(&req_entry->re_entry, &dev->dev_req_list); req->complete = gs_write_complete;
list_add(&req->list, &dev->dev_req_list);
} else { } else {
pr_err("gs_set_config: cannot allocate " pr_err("gs_set_config: cannot allocate "
"write requests\n"); "write requests\n");
...@@ -1986,7 +1838,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) ...@@ -1986,7 +1838,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
*/ */
static void gs_reset_config(struct gs_dev *dev) static void gs_reset_config(struct gs_dev *dev)
{ {
struct gs_req_entry *req_entry; struct usb_request *req;
if (dev == NULL) { if (dev == NULL) {
pr_err("gs_reset_config: NULL device pointer\n"); pr_err("gs_reset_config: NULL device pointer\n");
...@@ -2000,26 +1852,18 @@ static void gs_reset_config(struct gs_dev *dev) ...@@ -2000,26 +1852,18 @@ static void gs_reset_config(struct gs_dev *dev)
/* free write requests on the free list */ /* free write requests on the free list */
while(!list_empty(&dev->dev_req_list)) { while(!list_empty(&dev->dev_req_list)) {
req_entry = list_entry(dev->dev_req_list.next, req = list_entry(dev->dev_req_list.next,
struct gs_req_entry, re_entry); struct usb_request, list);
list_del(&req_entry->re_entry); list_del(&req->list);
gs_free_req_entry(dev->dev_in_ep, req_entry); gs_free_req(dev->dev_in_ep, req);
} }
/* disable endpoints, forcing completion of pending i/o; */ /* disable endpoints, forcing completion of pending i/o; */
/* completion handlers free their requests in this case */ /* completion handlers free their requests in this case */
if (dev->dev_notify_ep) { if (dev->dev_notify_ep)
usb_ep_disable(dev->dev_notify_ep); usb_ep_disable(dev->dev_notify_ep);
dev->dev_notify_ep = NULL; usb_ep_disable(dev->dev_in_ep);
} usb_ep_disable(dev->dev_out_ep);
if (dev->dev_in_ep) {
usb_ep_disable(dev->dev_in_ep);
dev->dev_in_ep = NULL;
}
if (dev->dev_out_ep) {
usb_ep_disable(dev->dev_out_ep);
dev->dev_out_ep = NULL;
}
} }
/* /*
...@@ -2112,46 +1956,6 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req) ...@@ -2112,46 +1956,6 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
} }
} }
/*
* gs_alloc_req_entry
*
* Allocates a request and its buffer, using the given
* endpoint, buffer len, and kmalloc flags.
*/
static struct gs_req_entry *
gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
{
struct gs_req_entry *req;
req = kmalloc(sizeof(struct gs_req_entry), kmalloc_flags);
if (req == NULL)
return NULL;
req->re_req = gs_alloc_req(ep, len, kmalloc_flags);
if (req->re_req == NULL) {
kfree(req);
return NULL;
}
req->re_req->context = req;
return req;
}
/*
* gs_free_req_entry
*
* Frees a request and its buffer.
*/
static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req)
{
if (ep != NULL && req != NULL) {
if (req->re_req != NULL)
gs_free_req(ep, req->re_req);
kfree(req);
}
}
/* /*
* gs_alloc_ports * gs_alloc_ports
* *
...@@ -2233,6 +2037,8 @@ static void gs_free_ports(struct gs_dev *dev) ...@@ -2233,6 +2037,8 @@ static void gs_free_ports(struct gs_dev *dev)
} }
} }
/*-------------------------------------------------------------------------*/
/* Circular Buffer */ /* Circular Buffer */
/* /*
...@@ -2393,3 +2199,77 @@ gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count) ...@@ -2393,3 +2199,77 @@ gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
return count; return count;
} }
/*-------------------------------------------------------------------------*/
static struct tty_driver *gs_tty_driver;
/*
* gs_module_init
*
* Register as a USB gadget driver and a tty driver.
*/
static int __init gs_module_init(void)
{
int i;
int retval;
retval = usb_gadget_register_driver(&gs_gadget_driver);
if (retval) {
pr_err("gs_module_init: cannot register gadget driver, "
"ret=%d\n", retval);
return retval;
}
gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS);
if (!gs_tty_driver)
return -ENOMEM;
gs_tty_driver->owner = THIS_MODULE;
gs_tty_driver->driver_name = GS_SHORT_NAME;
gs_tty_driver->name = "ttygs";
gs_tty_driver->major = GS_MAJOR;
gs_tty_driver->minor_start = GS_MINOR_START;
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
gs_tty_driver->init_termios = tty_std_termios;
/* must match GS_DEFAULT_DTE_RATE and friends */
gs_tty_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
gs_tty_driver->init_termios.c_ispeed = GS_DEFAULT_DTE_RATE;
gs_tty_driver->init_termios.c_ospeed = GS_DEFAULT_DTE_RATE;
tty_set_operations(gs_tty_driver, &gs_tty_ops);
for (i = 0; i < GS_NUM_PORTS; i++)
mutex_init(&gs_open_close_lock[i]);
retval = tty_register_driver(gs_tty_driver);
if (retval) {
usb_gadget_unregister_driver(&gs_gadget_driver);
put_tty_driver(gs_tty_driver);
pr_err("gs_module_init: cannot register tty driver, "
"ret=%d\n", retval);
return retval;
}
pr_info("gs_module_init: %s %s loaded\n",
GS_LONG_NAME, GS_VERSION_STR);
return 0;
}
module_init(gs_module_init);
/*
* gs_module_exit
*
* Unregister as a tty driver and a USB gadget driver.
*/
static void __exit gs_module_exit(void)
{
tty_unregister_driver(gs_tty_driver);
put_tty_driver(gs_tty_driver);
usb_gadget_unregister_driver(&gs_gadget_driver);
pr_info("gs_module_exit: %s %s unloaded\n",
GS_LONG_NAME, GS_VERSION_STR);
}
module_exit(gs_module_exit);
...@@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) ...@@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
* This did not trigger for a long time now. * This did not trigger for a long time now.
*/ */
printk(KERN_ERR "Reloading ptd %p/%p... qh %p readed: " printk(KERN_ERR "Reloading ptd %p/%p... qh %p readed: "
"%d of %d done: %08x cur: %08x\n", qtd, "%d of %zu done: %08x cur: %08x\n", qtd,
urb, qh, PTD_XFERRED_LENGTH(dw3), urb, qh, PTD_XFERRED_LENGTH(dw3),
qtd->length, done_map, qtd->length, done_map,
(1 << queue_entry)); (1 << queue_entry));
...@@ -1088,7 +1088,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) ...@@ -1088,7 +1088,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
} else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) { } else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) {
/* short BULK received */ /* short BULK received */
printk(KERN_ERR "short bulk, %d instead %d\n", length, printk(KERN_ERR "short bulk, %d instead %zu\n", length,
qtd->length); qtd->length);
if (urb->transfer_flags & URB_SHORT_NOT_OK) { if (urb->transfer_flags & URB_SHORT_NOT_OK) {
urb->status = -EREMOTEIO; urb->status = -EREMOTEIO;
......
...@@ -256,7 +256,7 @@ static struct pci_driver isp1761_pci_driver = { ...@@ -256,7 +256,7 @@ static struct pci_driver isp1761_pci_driver = {
static int __init isp1760_init(void) static int __init isp1760_init(void)
{ {
int ret; int ret = -ENODEV;
init_kmem_once(); init_kmem_once();
......
...@@ -90,7 +90,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) ...@@ -90,7 +90,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res, *mem; struct resource *res, *mem;
int retval, irq; int retval, irq;
struct usb_hcd *hcd = 0; struct usb_hcd *hcd = NULL;
irq = retval = platform_get_irq(pdev, 0); irq = retval = platform_get_irq(pdev, 0);
if (retval < 0) if (retval < 0)
......
...@@ -63,9 +63,6 @@ ...@@ -63,9 +63,6 @@
#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 #define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
#define USB_VENDOR_ID_MICROCHIP 0x04d8
#define USB_DEVICE_ID_PICDEM 0x000c
#ifdef CONFIG_USB_DYNAMIC_MINORS #ifdef CONFIG_USB_DYNAMIC_MINORS
#define USB_LD_MINOR_BASE 0 #define USB_LD_MINOR_BASE 0
#else #else
...@@ -92,7 +89,6 @@ static struct usb_device_id ld_usb_table [] = { ...@@ -92,7 +89,6 @@ static struct usb_device_id ld_usb_table [] = {
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
{ USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICDEM) },
{ USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -856,6 +856,11 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -856,6 +856,11 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
struct urb *u; struct urb *u;
struct usb_ctrlrequest req; struct usb_ctrlrequest req;
struct subcase *reqp; struct subcase *reqp;
/* sign of this variable means:
* -: tested code must return this (negative) error code
* +: tested code may return this (negative too) error code
*/
int expected = 0; int expected = 0;
/* requests here are mostly expected to succeed on any /* requests here are mostly expected to succeed on any
......
...@@ -447,6 +447,15 @@ config USB_SERIAL_MOS7840 ...@@ -447,6 +447,15 @@ config USB_SERIAL_MOS7840
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called mos7840. If unsure, choose N. module will be called mos7840. If unsure, choose N.
config USB_SERIAL_MOTOROLA
tristate "USB Motorola Phone modem driver"
---help---
Say Y here if you want to use a Motorola phone with a USB
connector as a modem link.
To compile this driver as a module, choose M here: the
module will be called moto_modem. If unsure, choose N.
config USB_SERIAL_NAVMAN config USB_SERIAL_NAVMAN
tristate "USB Navman GPS device" tristate "USB Navman GPS device"
help help
......
...@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o ...@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
obj-$(CONFIG_USB_SERIAL_MOS7720) += mos7720.o obj-$(CONFIG_USB_SERIAL_MOS7720) += mos7720.o
obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o
obj-$(CONFIG_USB_SERIAL_MOTOROLA) += moto_modem.o
obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
obj-$(CONFIG_USB_SERIAL_OPTION) += option.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
......
/*
* Motorola USB Phone driver
*
* Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* {sigh}
* Mororola should be using the CDC ACM USB spec, but instead
* they try to just "do their own thing"... This driver should handle a
* few phones in which a basic "dumb serial connection" is needed to be
* able to get a connection through to them.
*/
#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(0x05c6, 0x3197) }, /* unknown Motorola phone */
{ USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */
{ USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver moto_driver = {
.name = "moto-modem",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
.no_dynamic_id = 1,
};
static struct usb_serial_driver moto_device = {
.driver = {
.owner = THIS_MODULE,
.name = "moto-modem",
},
.id_table = id_table,
.num_ports = 1,
};
static int __init moto_init(void)
{
int retval;
retval = usb_serial_register(&moto_device);
if (retval)
return retval;
retval = usb_register(&moto_driver);
if (retval)
usb_serial_deregister(&moto_device);
return retval;
}
static void __exit moto_exit(void)
{
usb_deregister(&moto_driver);
usb_serial_deregister(&moto_device);
}
module_init(moto_init);
module_exit(moto_exit);
MODULE_LICENSE("GPL");
...@@ -154,8 +154,6 @@ static int option_send_setup(struct usb_serial_port *port); ...@@ -154,8 +154,6 @@ static int option_send_setup(struct usb_serial_port *port);
#define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC727 0x4100
#define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400
#define NOVATELWIRELESS_PRODUCT_U727 0x5010
/* FUTURE NOVATEL PRODUCTS */ /* FUTURE NOVATEL PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_EVDO_1 0x6000 #define NOVATELWIRELESS_PRODUCT_EVDO_1 0x6000
#define NOVATELWIRELESS_PRODUCT_HSPA_1 0x7000 #define NOVATELWIRELESS_PRODUCT_HSPA_1 0x7000
...@@ -184,6 +182,9 @@ static int option_send_setup(struct usb_serial_port *port); ...@@ -184,6 +182,9 @@ static int option_send_setup(struct usb_serial_port *port);
#define AXESSTEL_VENDOR_ID 0x1726 #define AXESSTEL_VENDOR_ID 0x1726
#define AXESSTEL_PRODUCT_MV110H 0x1000 #define AXESSTEL_PRODUCT_MV110H 0x1000
#define ONDA_VENDOR_ID 0x19d2
#define ONDA_PRODUCT_ET502HS 0x0002
#define BANDRICH_VENDOR_ID 0x1A8D #define BANDRICH_VENDOR_ID 0x1A8D
#define BANDRICH_PRODUCT_C100_1 0x1002 #define BANDRICH_PRODUCT_C100_1 0x1002
#define BANDRICH_PRODUCT_C100_2 0x1003 #define BANDRICH_PRODUCT_C100_2 0x1003
...@@ -269,7 +270,6 @@ static struct usb_device_id option_ids[] = { ...@@ -269,7 +270,6 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel U727 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_1) }, /* Novatel EVDO product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_1) }, /* Novatel EVDO product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_1) }, /* Novatel HSPA product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_1) }, /* Novatel HSPA product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_1) }, /* Novatel Embedded product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_1) }, /* Novatel Embedded product */
...@@ -293,14 +293,17 @@ static struct usb_device_id option_ids[] = { ...@@ -293,14 +293,17 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, 0x8133) }, /* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */ { USB_DEVICE(DELL_VENDOR_ID, 0x8133) }, /* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */ { USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */ { USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
{ USB_DEVICE(0x19d2, 0x0001) }, /* Telstra NextG CDMA */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, option_ids); MODULE_DEVICE_TABLE(usb, option_ids);
......
...@@ -401,6 +401,14 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, ...@@ -401,6 +401,14 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999,
"Cypress",
"Cypress AT2LP",
US_SC_CYP_ATACB, US_PR_BULK, NULL,
0),
#endif
/* Reported by Simon Levitt <simon@whattf.com> /* Reported by Simon Levitt <simon@whattf.com>
* This entry needs Sub and Proto fields */ * This entry needs Sub and Proto fields */
UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100,
...@@ -539,17 +547,6 @@ UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, ...@@ -539,17 +547,6 @@ UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200,
"CD-RW Device", "CD-RW Device",
US_SC_8020, US_PR_CB, NULL, 0), US_SC_8020, US_PR_CB, NULL, 0),
/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
* Device uses standards-violating 32-byte Bulk Command Block Wrappers and
* reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
*/
UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100,
"Kobian Mercury",
"Binocam DCB-132",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_BULK32),
#ifdef CONFIG_USB_STORAGE_USBAT #ifdef CONFIG_USB_STORAGE_USBAT
UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999,
"Shuttle/SCM", "Shuttle/SCM",
...@@ -565,6 +562,16 @@ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, ...@@ -565,6 +562,16 @@ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64), US_FL_MAX_SECTORS_64),
/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
* Device uses standards-violating 32-byte Bulk Command Block Wrappers and
* reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
*/
UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100,
"Kobian Mercury",
"Binocam DCB-132",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_BULK32),
/* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */ /* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133, UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
"Belkin", "Belkin",
...@@ -1304,6 +1311,16 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, ...@@ -1304,6 +1311,16 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE ), US_FL_IGNORE_DEVICE ),
/* Reported by F. Aben <f.aben@option.com>
* This device (wrongly) has a vendor-specific device descriptor.
* The entry is needed so usb-storage can bind to it's mass-storage
* interface as an interface driver */
UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000,
"Option",
"GI 0401 SD-Card",
US_SC_DEVICE, US_PR_DEVICE, NULL,
0 ),
#ifdef CONFIG_USB_STORAGE_ISD200 #ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI", "ATI",
...@@ -1361,13 +1378,6 @@ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, ...@@ -1361,13 +1378,6 @@ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY), US_FL_FIX_INQUIRY),
/* Reported by Rohan Hart <rohan.hart17@gmail.com> */
UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010,
"INTOVA",
"Pixtreme",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
/* /*
* Entry for Jenoptik JD 5200z3 * Entry for Jenoptik JD 5200z3
* *
...@@ -1684,6 +1694,16 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, ...@@ -1684,6 +1694,16 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Reported by Mauro Andreolini <andreoli@weblab.ing.unimo.it>
* This entry is needed to bypass the ZeroCD mechanism
* and to properly load as a modem device.
*/
UNUSUAL_DEV( 0x19d2, 0x2000, 0x0000, 0x0000,
"Onda ET502HS",
"USB MMC Storage",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE),
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org> /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
* and Renato Perini <rperini@email.it> * and Renato Perini <rperini@email.it>
*/ */
...@@ -1721,6 +1741,13 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, ...@@ -1721,6 +1741,13 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_GO_SLOW ), US_FL_GO_SLOW ),
/* Reported by Rohan Hart <rohan.hart17@gmail.com> */
UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010,
"INTOVA",
"Pixtreme",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
/* /*
* David Härdeman <david@2gen.com> * David Härdeman <david@2gen.com>
* The key makes the SCSI stack print confusing (but harmless) messages * The key makes the SCSI stack print confusing (but harmless) messages
...@@ -1745,14 +1772,6 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, ...@@ -1745,14 +1772,6 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_CAPACITY_HEURISTICS), US_FL_CAPACITY_HEURISTICS),
#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999,
"Cypress",
"Cypress AT2LP",
US_SC_CYP_ATACB, US_PR_BULK, NULL,
0),
#endif
/* Control/Bulk transport for all SubClass values */ /* Control/Bulk transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
......
/*
* Wireless USB - Cable Based Association
*
* Copyright (C) 2006 Intel Corporation
* Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
*/
#ifndef __LINUX_USB_ASSOCIATION_H
#define __LINUX_USB_ASSOCIATION_H
/*
* Association attributes
*
* Association Models Supplement to WUSB 1.0 T[3-1]
*
* Each field in the structures has it's ID, it's length and then the
* value. This is the actual definition of the field's ID and its
* length.
*/
struct wusb_am_attr {
__u8 id;
__u8 len;
};
/* Different fields defined by the spec */
#define WUSB_AR_AssociationTypeId { .id = 0x0000, .len = 2 }
#define WUSB_AR_AssociationSubTypeId { .id = 0x0001, .len = 2 }
#define WUSB_AR_Length { .id = 0x0002, .len = 4 }
#define WUSB_AR_AssociationStatus { .id = 0x0004, .len = 4 }
#define WUSB_AR_LangID { .id = 0x0008, .len = 2 }
#define WUSB_AR_DeviceFriendlyName { .id = 0x000b, .len = 64 } /* max */
#define WUSB_AR_HostFriendlyName { .id = 0x000c, .len = 64 } /* max */
#define WUSB_AR_CHID { .id = 0x1000, .len = 16 }
#define WUSB_AR_CDID { .id = 0x1001, .len = 16 }
#define WUSB_AR_ConnectionContext { .id = 0x1002, .len = 48 }
#define WUSB_AR_BandGroups { .id = 0x1004, .len = 2 }
/* CBAF Control Requests (AMS1.0[T4-1] */
enum {
CBAF_REQ_GET_ASSOCIATION_INFORMATION = 0x01,
CBAF_REQ_GET_ASSOCIATION_REQUEST,
CBAF_REQ_SET_ASSOCIATION_RESPONSE
};
/*
* CBAF USB-interface defitions
*
* No altsettings, one optional interrupt endpoint.
*/
enum {
CBAF_IFACECLASS = 0xef,
CBAF_IFACESUBCLASS = 0x03,
CBAF_IFACEPROTOCOL = 0x01,
};
/* Association Information (AMS1.0[T4-3]) */
struct wusb_cbaf_assoc_info {
__le16 Length;
__u8 NumAssociationRequests;
__le16 Flags;
__u8 AssociationRequestsArray[];
} __attribute__((packed));
/* Association Request (AMS1.0[T4-4]) */
struct wusb_cbaf_assoc_request {
__u8 AssociationDataIndex;
__u8 Reserved;
__le16 AssociationTypeId;
__le16 AssociationSubTypeId;
__le32 AssociationTypeInfoSize;
} __attribute__((packed));
enum {
AR_TYPE_WUSB = 0x0001,
AR_TYPE_WUSB_RETRIEVE_HOST_INFO = 0x0000,
AR_TYPE_WUSB_ASSOCIATE = 0x0001,
};
/* Association Attribute header (AMS1.0[3.8]) */
struct wusb_cbaf_attr_hdr {
__le16 id;
__le16 len;
} __attribute__((packed));
/* Host Info (AMS1.0[T4-7]) (yeah, more headers and fields...) */
struct wusb_cbaf_host_info {
struct wusb_cbaf_attr_hdr AssociationTypeId_hdr;
__le16 AssociationTypeId;
struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr;
__le16 AssociationSubTypeId;
struct wusb_cbaf_attr_hdr CHID_hdr;
struct wusb_ckhdid CHID;
struct wusb_cbaf_attr_hdr LangID_hdr;
__le16 LangID;
struct wusb_cbaf_attr_hdr HostFriendlyName_hdr;
__u8 HostFriendlyName[];
} __attribute__((packed));
/* Device Info (AMS1.0[T4-8])
*
* I still don't get this tag'n'header stuff for each goddamn
* field...
*/
struct wusb_cbaf_device_info {
struct wusb_cbaf_attr_hdr Length_hdr;
__le32 Length;
struct wusb_cbaf_attr_hdr CDID_hdr;
struct wusb_ckhdid CDID;
struct wusb_cbaf_attr_hdr BandGroups_hdr;
__le16 BandGroups;
struct wusb_cbaf_attr_hdr LangID_hdr;
__le16 LangID;
struct wusb_cbaf_attr_hdr DeviceFriendlyName_hdr;
__u8 DeviceFriendlyName[];
} __attribute__((packed));
/* Connection Context; CC_DATA - Success case (AMS1.0[T4-9]) */
struct wusb_cbaf_cc_data {
struct wusb_cbaf_attr_hdr AssociationTypeId_hdr;
__le16 AssociationTypeId;
struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr;
__le16 AssociationSubTypeId;
struct wusb_cbaf_attr_hdr Length_hdr;
__le32 Length;
struct wusb_cbaf_attr_hdr ConnectionContext_hdr;
struct wusb_ckhdid CHID;
struct wusb_ckhdid CDID;
struct wusb_ckhdid CK;
struct wusb_cbaf_attr_hdr BandGroups_hdr;
__le16 BandGroups;
} __attribute__((packed));
/* CC_DATA - Failure case (AMS1.0[T4-10]) */
struct wusb_cbaf_cc_data_fail {
struct wusb_cbaf_attr_hdr AssociationTypeId_hdr;
__le16 AssociationTypeId;
struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr;
__le16 AssociationSubTypeId;
struct wusb_cbaf_attr_hdr Length_hdr;
__le16 Length;
struct wusb_cbaf_attr_hdr AssociationStatus_hdr;
__u32 AssociationStatus;
} __attribute__((packed));
#endif /* __LINUX_USB_ASSOCIATION_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册