diff options
Diffstat (limited to 'drivers/usb')
149 files changed, 19894 insertions, 3945 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 005043197527..f9b1719b9a37 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -25,6 +25,7 @@ config USB_ARCH_HAS_OHCI | |||
25 | default y if PXA27x | 25 | default y if PXA27x |
26 | default y if ARCH_EP93XX | 26 | default y if ARCH_EP93XX |
27 | default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) | 27 | default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) |
28 | default y if ARCH_PNX4008 | ||
28 | # PPC: | 29 | # PPC: |
29 | default y if STB03xxx | 30 | default y if STB03xxx |
30 | default y if PPC_MPC52xx | 31 | default y if PPC_MPC52xx |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 4710eb02ed64..97d57cfc343b 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_ISP116X_HCD) += host/ | |||
14 | obj-$(CONFIG_USB_OHCI_HCD) += host/ | 14 | obj-$(CONFIG_USB_OHCI_HCD) += host/ |
15 | obj-$(CONFIG_USB_UHCI_HCD) += host/ | 15 | obj-$(CONFIG_USB_UHCI_HCD) += host/ |
16 | obj-$(CONFIG_USB_SL811_HCD) += host/ | 16 | obj-$(CONFIG_USB_SL811_HCD) += host/ |
17 | obj-$(CONFIG_USB_U132_HCD) += host/ | ||
17 | obj-$(CONFIG_ETRAX_USB_HOST) += host/ | 18 | obj-$(CONFIG_ETRAX_USB_HOST) += host/ |
18 | obj-$(CONFIG_USB_OHCI_AT91) += host/ | 19 | obj-$(CONFIG_USB_OHCI_AT91) += host/ |
19 | 20 | ||
@@ -23,6 +24,7 @@ obj-$(CONFIG_USB_PRINTER) += class/ | |||
23 | obj-$(CONFIG_USB_STORAGE) += storage/ | 24 | obj-$(CONFIG_USB_STORAGE) += storage/ |
24 | obj-$(CONFIG_USB) += storage/ | 25 | obj-$(CONFIG_USB) += storage/ |
25 | 26 | ||
27 | obj-$(CONFIG_USB_ACECAD) += input/ | ||
26 | obj-$(CONFIG_USB_AIPTEK) += input/ | 28 | obj-$(CONFIG_USB_AIPTEK) += input/ |
27 | obj-$(CONFIG_USB_ATI_REMOTE) += input/ | 29 | obj-$(CONFIG_USB_ATI_REMOTE) += input/ |
28 | obj-$(CONFIG_USB_HID) += input/ | 30 | obj-$(CONFIG_USB_HID) += input/ |
@@ -31,8 +33,8 @@ obj-$(CONFIG_USB_KBTAB) += input/ | |||
31 | obj-$(CONFIG_USB_MOUSE) += input/ | 33 | obj-$(CONFIG_USB_MOUSE) += input/ |
32 | obj-$(CONFIG_USB_MTOUCH) += input/ | 34 | obj-$(CONFIG_USB_MTOUCH) += input/ |
33 | obj-$(CONFIG_USB_POWERMATE) += input/ | 35 | obj-$(CONFIG_USB_POWERMATE) += input/ |
36 | obj-$(CONFIG_USB_TRANCEVIBRATOR)+= input/ | ||
34 | obj-$(CONFIG_USB_WACOM) += input/ | 37 | obj-$(CONFIG_USB_WACOM) += input/ |
35 | obj-$(CONFIG_USB_ACECAD) += input/ | ||
36 | obj-$(CONFIG_USB_XPAD) += input/ | 38 | obj-$(CONFIG_USB_XPAD) += input/ |
37 | 39 | ||
38 | obj-$(CONFIG_USB_CATC) += net/ | 40 | obj-$(CONFIG_USB_CATC) += net/ |
@@ -47,22 +49,24 @@ obj-$(CONFIG_USB_MICROTEK) += image/ | |||
47 | 49 | ||
48 | obj-$(CONFIG_USB_SERIAL) += serial/ | 50 | obj-$(CONFIG_USB_SERIAL) += serial/ |
49 | 51 | ||
52 | obj-$(CONFIG_USB_ADUTUX) += misc/ | ||
53 | obj-$(CONFIG_USB_APPLEDISPLAY) += misc/ | ||
50 | obj-$(CONFIG_USB_AUERSWALD) += misc/ | 54 | obj-$(CONFIG_USB_AUERSWALD) += misc/ |
51 | obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/ | 55 | obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/ |
52 | obj-$(CONFIG_USB_CYTHERM) += misc/ | 56 | obj-$(CONFIG_USB_CYTHERM) += misc/ |
53 | obj-$(CONFIG_USB_EMI26) += misc/ | 57 | obj-$(CONFIG_USB_EMI26) += misc/ |
54 | obj-$(CONFIG_USB_EMI62) += misc/ | 58 | obj-$(CONFIG_USB_EMI62) += misc/ |
59 | obj-$(CONFIG_USB_FTDI_ELAN) += misc/ | ||
55 | obj-$(CONFIG_USB_IDMOUSE) += misc/ | 60 | obj-$(CONFIG_USB_IDMOUSE) += misc/ |
56 | obj-$(CONFIG_USB_LCD) += misc/ | 61 | obj-$(CONFIG_USB_LCD) += misc/ |
57 | obj-$(CONFIG_USB_LD) += misc/ | 62 | obj-$(CONFIG_USB_LD) += misc/ |
58 | obj-$(CONFIG_USB_LED) += misc/ | 63 | obj-$(CONFIG_USB_LED) += misc/ |
59 | obj-$(CONFIG_USB_LEGOTOWER) += misc/ | 64 | obj-$(CONFIG_USB_LEGOTOWER) += misc/ |
65 | obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ | ||
60 | obj-$(CONFIG_USB_RIO500) += misc/ | 66 | obj-$(CONFIG_USB_RIO500) += misc/ |
67 | obj-$(CONFIG_USB_SISUSBVGA) += misc/ | ||
61 | obj-$(CONFIG_USB_TEST) += misc/ | 68 | obj-$(CONFIG_USB_TEST) += misc/ |
62 | obj-$(CONFIG_USB_USS720) += misc/ | 69 | obj-$(CONFIG_USB_USS720) += misc/ |
63 | obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ | ||
64 | obj-$(CONFIG_USB_SISUSBVGA) += misc/ | ||
65 | obj-$(CONFIG_USB_APPLEDISPLAY) += misc/ | ||
66 | 70 | ||
67 | obj-$(CONFIG_USB_ATM) += atm/ | 71 | obj-$(CONFIG_USB_ATM) += atm/ |
68 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ | 72 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ |
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index b38990adf1cd..465961a26e4a 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -1621,26 +1621,32 @@ static int claim_interface(struct usb_device *usb_dev, | |||
1621 | return ret; | 1621 | return ret; |
1622 | } | 1622 | } |
1623 | 1623 | ||
1624 | static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf) | 1624 | static struct attribute *attrs[] = { |
1625 | &dev_attr_stat_status.attr, | ||
1626 | &dev_attr_stat_mflags.attr, | ||
1627 | &dev_attr_stat_human_status.attr, | ||
1628 | &dev_attr_stat_delin.attr, | ||
1629 | &dev_attr_stat_vidcpe.attr, | ||
1630 | &dev_attr_stat_usrate.attr, | ||
1631 | &dev_attr_stat_dsrate.attr, | ||
1632 | &dev_attr_stat_usattenuation.attr, | ||
1633 | &dev_attr_stat_dsattenuation.attr, | ||
1634 | &dev_attr_stat_usmargin.attr, | ||
1635 | &dev_attr_stat_dsmargin.attr, | ||
1636 | &dev_attr_stat_txflow.attr, | ||
1637 | &dev_attr_stat_rxflow.attr, | ||
1638 | &dev_attr_stat_uscorr.attr, | ||
1639 | &dev_attr_stat_dscorr.attr, | ||
1640 | &dev_attr_stat_usunc.attr, | ||
1641 | &dev_attr_stat_dsunc.attr, | ||
1642 | }; | ||
1643 | static struct attribute_group attr_grp = { | ||
1644 | .attrs = attrs, | ||
1645 | }; | ||
1646 | |||
1647 | static int create_fs_entries(struct usb_interface *intf) | ||
1625 | { | 1648 | { |
1626 | /* sysfs interface */ | 1649 | return sysfs_create_group(&intf->dev.kobj, &attr_grp); |
1627 | device_create_file(&intf->dev, &dev_attr_stat_status); | ||
1628 | device_create_file(&intf->dev, &dev_attr_stat_mflags); | ||
1629 | device_create_file(&intf->dev, &dev_attr_stat_human_status); | ||
1630 | device_create_file(&intf->dev, &dev_attr_stat_delin); | ||
1631 | device_create_file(&intf->dev, &dev_attr_stat_vidcpe); | ||
1632 | device_create_file(&intf->dev, &dev_attr_stat_usrate); | ||
1633 | device_create_file(&intf->dev, &dev_attr_stat_dsrate); | ||
1634 | device_create_file(&intf->dev, &dev_attr_stat_usattenuation); | ||
1635 | device_create_file(&intf->dev, &dev_attr_stat_dsattenuation); | ||
1636 | device_create_file(&intf->dev, &dev_attr_stat_usmargin); | ||
1637 | device_create_file(&intf->dev, &dev_attr_stat_dsmargin); | ||
1638 | device_create_file(&intf->dev, &dev_attr_stat_txflow); | ||
1639 | device_create_file(&intf->dev, &dev_attr_stat_rxflow); | ||
1640 | device_create_file(&intf->dev, &dev_attr_stat_uscorr); | ||
1641 | device_create_file(&intf->dev, &dev_attr_stat_dscorr); | ||
1642 | device_create_file(&intf->dev, &dev_attr_stat_usunc); | ||
1643 | device_create_file(&intf->dev, &dev_attr_stat_dsunc); | ||
1644 | } | 1650 | } |
1645 | 1651 | ||
1646 | static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, | 1652 | static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, |
@@ -1708,37 +1714,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, | |||
1708 | return ret; | 1714 | return ret; |
1709 | } | 1715 | } |
1710 | 1716 | ||
1711 | create_fs_entries(sc, intf); | 1717 | ret = create_fs_entries(intf); |
1718 | if (ret) { | ||
1719 | uea_stop(sc); | ||
1720 | kfree(sc); | ||
1721 | return ret; | ||
1722 | } | ||
1712 | return 0; | 1723 | return 0; |
1713 | } | 1724 | } |
1714 | 1725 | ||
1715 | static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf) | 1726 | static void destroy_fs_entries(struct usb_interface *intf) |
1716 | { | 1727 | { |
1717 | /* sysfs interface */ | 1728 | sysfs_remove_group(&intf->dev.kobj, &attr_grp); |
1718 | device_remove_file(&intf->dev, &dev_attr_stat_status); | ||
1719 | device_remove_file(&intf->dev, &dev_attr_stat_mflags); | ||
1720 | device_remove_file(&intf->dev, &dev_attr_stat_human_status); | ||
1721 | device_remove_file(&intf->dev, &dev_attr_stat_delin); | ||
1722 | device_remove_file(&intf->dev, &dev_attr_stat_vidcpe); | ||
1723 | device_remove_file(&intf->dev, &dev_attr_stat_usrate); | ||
1724 | device_remove_file(&intf->dev, &dev_attr_stat_dsrate); | ||
1725 | device_remove_file(&intf->dev, &dev_attr_stat_usattenuation); | ||
1726 | device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation); | ||
1727 | device_remove_file(&intf->dev, &dev_attr_stat_usmargin); | ||
1728 | device_remove_file(&intf->dev, &dev_attr_stat_dsmargin); | ||
1729 | device_remove_file(&intf->dev, &dev_attr_stat_txflow); | ||
1730 | device_remove_file(&intf->dev, &dev_attr_stat_rxflow); | ||
1731 | device_remove_file(&intf->dev, &dev_attr_stat_uscorr); | ||
1732 | device_remove_file(&intf->dev, &dev_attr_stat_dscorr); | ||
1733 | device_remove_file(&intf->dev, &dev_attr_stat_usunc); | ||
1734 | device_remove_file(&intf->dev, &dev_attr_stat_dsunc); | ||
1735 | } | 1729 | } |
1736 | 1730 | ||
1737 | static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) | 1731 | static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) |
1738 | { | 1732 | { |
1739 | struct uea_softc *sc = usbatm->driver_data; | 1733 | struct uea_softc *sc = usbatm->driver_data; |
1740 | 1734 | ||
1741 | destroy_fs_entries(sc, intf); | 1735 | destroy_fs_entries(intf); |
1742 | uea_stop(sc); | 1736 | uea_stop(sc); |
1743 | kfree(sc); | 1737 | kfree(sc); |
1744 | } | 1738 | } |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 48dee4b8d8e5..9cac11ca1bb7 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -813,7 +813,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product) | |||
813 | return 0; | 813 | return 0; |
814 | } | 814 | } |
815 | 815 | ||
816 | static struct file_operations usblp_fops = { | 816 | static const struct file_operations usblp_fops = { |
817 | .owner = THIS_MODULE, | 817 | .owner = THIS_MODULE, |
818 | .read = usblp_read, | 818 | .read = usblp_read, |
819 | .write = usblp_write, | 819 | .write = usblp_write, |
@@ -927,7 +927,9 @@ static int usblp_probe(struct usb_interface *intf, | |||
927 | 927 | ||
928 | /* Retrieve and store the device ID string. */ | 928 | /* Retrieve and store the device ID string. */ |
929 | usblp_cache_device_id_string(usblp); | 929 | usblp_cache_device_id_string(usblp); |
930 | device_create_file(&intf->dev, &dev_attr_ieee1284_id); | 930 | retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id); |
931 | if (retval) | ||
932 | goto abort_intfdata; | ||
931 | 933 | ||
932 | #ifdef DEBUG | 934 | #ifdef DEBUG |
933 | usblp_check_status(usblp, 0); | 935 | usblp_check_status(usblp, 0); |
@@ -1021,18 +1023,13 @@ static int usblp_select_alts(struct usblp *usblp) | |||
1021 | for (e = 0; e < ifd->desc.bNumEndpoints; e++) { | 1023 | for (e = 0; e < ifd->desc.bNumEndpoints; e++) { |
1022 | epd = &ifd->endpoint[e].desc; | 1024 | epd = &ifd->endpoint[e].desc; |
1023 | 1025 | ||
1024 | if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!= | 1026 | if (usb_endpoint_is_bulk_out(epd)) |
1025 | USB_ENDPOINT_XFER_BULK) | ||
1026 | continue; | ||
1027 | |||
1028 | if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) { | ||
1029 | if (!epwrite) | 1027 | if (!epwrite) |
1030 | epwrite = epd; | 1028 | epwrite = epd; |
1031 | 1029 | ||
1032 | } else { | 1030 | if (usb_endpoint_is_bulk_in(epd)) |
1033 | if (!epread) | 1031 | if (!epread) |
1034 | epread = epd; | 1032 | epread = epd; |
1035 | } | ||
1036 | } | 1033 | } |
1037 | 1034 | ||
1038 | /* Ignore buggy hardware without the right endpoints. */ | 1035 | /* Ignore buggy hardware without the right endpoints. */ |
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index ec510922af63..34e9bac319b4 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ | 5 | usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ |
6 | config.o file.o buffer.o sysfs.o endpoint.o \ | 6 | config.o file.o buffer.o sysfs.o endpoint.o \ |
7 | devio.o notify.o | 7 | devio.o notify.o generic.o |
8 | 8 | ||
9 | ifeq ($(CONFIG_PCI),y) | 9 | ifeq ($(CONFIG_PCI),y) |
10 | usbcore-objs += hcd-pci.o | 10 | usbcore-objs += hcd-pci.o |
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index f4f4ef0f377a..840442a25b61 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c | |||
@@ -104,7 +104,7 @@ void *hcd_buffer_alloc ( | |||
104 | dma_addr_t *dma | 104 | dma_addr_t *dma |
105 | ) | 105 | ) |
106 | { | 106 | { |
107 | struct usb_hcd *hcd = bus->hcpriv; | 107 | struct usb_hcd *hcd = bus_to_hcd(bus); |
108 | int i; | 108 | int i; |
109 | 109 | ||
110 | /* some USB hosts just use PIO */ | 110 | /* some USB hosts just use PIO */ |
@@ -127,7 +127,7 @@ void hcd_buffer_free ( | |||
127 | dma_addr_t dma | 127 | dma_addr_t dma |
128 | ) | 128 | ) |
129 | { | 129 | { |
130 | struct usb_hcd *hcd = bus->hcpriv; | 130 | struct usb_hcd *hcd = bus_to_hcd(bus); |
131 | int i; | 131 | int i; |
132 | 132 | ||
133 | if (!addr) | 133 | if (!addr) |
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 4c9e63e665b6..bfb3731d42db 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
@@ -475,7 +475,9 @@ int usb_get_configuration(struct usb_device *dev) | |||
475 | if (result < 0) { | 475 | if (result < 0) { |
476 | dev_err(ddev, "unable to read config index %d " | 476 | dev_err(ddev, "unable to read config index %d " |
477 | "descriptor/%s\n", cfgno, "start"); | 477 | "descriptor/%s\n", cfgno, "start"); |
478 | goto err; | 478 | dev_err(ddev, "chopping to %d config(s)\n", cfgno); |
479 | dev->descriptor.bNumConfigurations = cfgno; | ||
480 | break; | ||
479 | } else if (result < 4) { | 481 | } else if (result < 4) { |
480 | dev_err(ddev, "config index %d descriptor too short " | 482 | dev_err(ddev, "config index %d descriptor too short " |
481 | "(expected %i, got %i)\n", cfgno, | 483 | "(expected %i, got %i)\n", cfgno, |
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index c0f37343a276..3538c2fdadfe 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
@@ -593,7 +593,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte | |||
593 | /* Kernel lock for "lastev" protection */ | 593 | /* Kernel lock for "lastev" protection */ |
594 | static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait) | 594 | static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait) |
595 | { | 595 | { |
596 | struct usb_device_status *st = (struct usb_device_status *)file->private_data; | 596 | struct usb_device_status *st = file->private_data; |
597 | unsigned int mask = 0; | 597 | unsigned int mask = 0; |
598 | 598 | ||
599 | lock_kernel(); | 599 | lock_kernel(); |
@@ -603,7 +603,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct | |||
603 | unlock_kernel(); | 603 | unlock_kernel(); |
604 | return POLLIN; | 604 | return POLLIN; |
605 | } | 605 | } |
606 | 606 | ||
607 | /* we may have dropped BKL - need to check for having lost the race */ | 607 | /* we may have dropped BKL - need to check for having lost the race */ |
608 | if (file->private_data) { | 608 | if (file->private_data) { |
609 | kfree(st); | 609 | kfree(st); |
@@ -667,7 +667,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig) | |||
667 | return ret; | 667 | return ret; |
668 | } | 668 | } |
669 | 669 | ||
670 | struct file_operations usbfs_devices_fops = { | 670 | const struct file_operations usbfs_devices_fops = { |
671 | .llseek = usb_device_lseek, | 671 | .llseek = usb_device_lseek, |
672 | .read = usb_device_read, | 672 | .read = usb_device_read, |
673 | .poll = usb_device_poll, | 673 | .poll = usb_device_poll, |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 218621b9958e..a94c63bef632 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -59,6 +59,9 @@ | |||
59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 | 59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 |
60 | static struct class *usb_device_class; | 60 | static struct class *usb_device_class; |
61 | 61 | ||
62 | /* Mutual exclusion for removal, open, and release */ | ||
63 | DEFINE_MUTEX(usbfs_mutex); | ||
64 | |||
62 | struct async { | 65 | struct async { |
63 | struct list_head asynclist; | 66 | struct list_head asynclist; |
64 | struct dev_state *ps; | 67 | struct dev_state *ps; |
@@ -87,9 +90,10 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic"); | |||
87 | 90 | ||
88 | #define MAX_USBFS_BUFFER_SIZE 16384 | 91 | #define MAX_USBFS_BUFFER_SIZE 16384 |
89 | 92 | ||
90 | static inline int connected (struct usb_device *dev) | 93 | static inline int connected (struct dev_state *ps) |
91 | { | 94 | { |
92 | return dev->state != USB_STATE_NOTATTACHED; | 95 | return (!list_empty(&ps->list) && |
96 | ps->dev->state != USB_STATE_NOTATTACHED); | ||
93 | } | 97 | } |
94 | 98 | ||
95 | static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) | 99 | static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) |
@@ -118,7 +122,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) | |||
118 | 122 | ||
119 | static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | 123 | static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) |
120 | { | 124 | { |
121 | struct dev_state *ps = (struct dev_state *)file->private_data; | 125 | struct dev_state *ps = file->private_data; |
122 | struct usb_device *dev = ps->dev; | 126 | struct usb_device *dev = ps->dev; |
123 | ssize_t ret = 0; | 127 | ssize_t ret = 0; |
124 | unsigned len; | 128 | unsigned len; |
@@ -127,7 +131,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l | |||
127 | 131 | ||
128 | pos = *ppos; | 132 | pos = *ppos; |
129 | usb_lock_device(dev); | 133 | usb_lock_device(dev); |
130 | if (!connected(dev)) { | 134 | if (!connected(ps)) { |
131 | ret = -ENODEV; | 135 | ret = -ENODEV; |
132 | goto err; | 136 | goto err; |
133 | } else if (pos < 0) { | 137 | } else if (pos < 0) { |
@@ -301,7 +305,7 @@ static void snoop_urb(struct urb *urb, void __user *userurb) | |||
301 | 305 | ||
302 | static void async_completed(struct urb *urb, struct pt_regs *regs) | 306 | static void async_completed(struct urb *urb, struct pt_regs *regs) |
303 | { | 307 | { |
304 | struct async *as = (struct async *)urb->context; | 308 | struct async *as = urb->context; |
305 | struct dev_state *ps = as->ps; | 309 | struct dev_state *ps = as->ps; |
306 | struct siginfo sinfo; | 310 | struct siginfo sinfo; |
307 | 311 | ||
@@ -541,25 +545,25 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
541 | struct dev_state *ps; | 545 | struct dev_state *ps; |
542 | int ret; | 546 | int ret; |
543 | 547 | ||
544 | /* | 548 | /* Protect against simultaneous removal or release */ |
545 | * no locking necessary here, as chrdev_open has the kernel lock | 549 | mutex_lock(&usbfs_mutex); |
546 | * (still acquire the kernel lock for safety) | 550 | |
547 | */ | ||
548 | ret = -ENOMEM; | 551 | ret = -ENOMEM; |
549 | if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL))) | 552 | if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL))) |
550 | goto out_nolock; | 553 | goto out; |
551 | 554 | ||
552 | lock_kernel(); | ||
553 | ret = -ENOENT; | 555 | ret = -ENOENT; |
554 | /* check if we are called from a real node or usbfs */ | 556 | /* check if we are called from a real node or usbfs */ |
555 | if (imajor(inode) == USB_DEVICE_MAJOR) | 557 | if (imajor(inode) == USB_DEVICE_MAJOR) |
556 | dev = usbdev_lookup_minor(iminor(inode)); | 558 | dev = usbdev_lookup_minor(iminor(inode)); |
557 | if (!dev) | 559 | if (!dev) |
558 | dev = inode->u.generic_ip; | 560 | dev = inode->i_private; |
559 | if (!dev) { | 561 | if (!dev) |
560 | kfree(ps); | ||
561 | goto out; | 562 | goto out; |
562 | } | 563 | ret = usb_autoresume_device(dev, 1); |
564 | if (ret) | ||
565 | goto out; | ||
566 | |||
563 | usb_get_dev(dev); | 567 | usb_get_dev(dev); |
564 | ret = 0; | 568 | ret = 0; |
565 | ps->dev = dev; | 569 | ps->dev = dev; |
@@ -579,30 +583,36 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
579 | list_add_tail(&ps->list, &dev->filelist); | 583 | list_add_tail(&ps->list, &dev->filelist); |
580 | file->private_data = ps; | 584 | file->private_data = ps; |
581 | out: | 585 | out: |
582 | unlock_kernel(); | 586 | if (ret) |
583 | out_nolock: | 587 | kfree(ps); |
584 | return ret; | 588 | mutex_unlock(&usbfs_mutex); |
589 | return ret; | ||
585 | } | 590 | } |
586 | 591 | ||
587 | static int usbdev_release(struct inode *inode, struct file *file) | 592 | static int usbdev_release(struct inode *inode, struct file *file) |
588 | { | 593 | { |
589 | struct dev_state *ps = (struct dev_state *)file->private_data; | 594 | struct dev_state *ps = file->private_data; |
590 | struct usb_device *dev = ps->dev; | 595 | struct usb_device *dev = ps->dev; |
591 | unsigned int ifnum; | 596 | unsigned int ifnum; |
592 | 597 | ||
593 | usb_lock_device(dev); | 598 | usb_lock_device(dev); |
599 | |||
600 | /* Protect against simultaneous open */ | ||
601 | mutex_lock(&usbfs_mutex); | ||
594 | list_del_init(&ps->list); | 602 | list_del_init(&ps->list); |
603 | mutex_unlock(&usbfs_mutex); | ||
604 | |||
595 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); | 605 | for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); |
596 | ifnum++) { | 606 | ifnum++) { |
597 | if (test_bit(ifnum, &ps->ifclaimed)) | 607 | if (test_bit(ifnum, &ps->ifclaimed)) |
598 | releaseintf(ps, ifnum); | 608 | releaseintf(ps, ifnum); |
599 | } | 609 | } |
600 | destroy_all_async(ps); | 610 | destroy_all_async(ps); |
611 | usb_autosuspend_device(dev, 1); | ||
601 | usb_unlock_device(dev); | 612 | usb_unlock_device(dev); |
602 | usb_put_dev(dev); | 613 | usb_put_dev(dev); |
603 | ps->dev = NULL; | ||
604 | kfree(ps); | 614 | kfree(ps); |
605 | return 0; | 615 | return 0; |
606 | } | 616 | } |
607 | 617 | ||
608 | static int proc_control(struct dev_state *ps, void __user *arg) | 618 | static int proc_control(struct dev_state *ps, void __user *arg) |
@@ -1322,7 +1332,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1322 | } | 1332 | } |
1323 | } | 1333 | } |
1324 | 1334 | ||
1325 | if (!connected(ps->dev)) { | 1335 | if (!connected(ps)) { |
1326 | kfree(buf); | 1336 | kfree(buf); |
1327 | return -ENODEV; | 1337 | return -ENODEV; |
1328 | } | 1338 | } |
@@ -1349,7 +1359,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1349 | /* let kernel drivers try to (re)bind to the interface */ | 1359 | /* let kernel drivers try to (re)bind to the interface */ |
1350 | case USBDEVFS_CONNECT: | 1360 | case USBDEVFS_CONNECT: |
1351 | usb_unlock_device(ps->dev); | 1361 | usb_unlock_device(ps->dev); |
1352 | bus_rescan_devices(intf->dev.bus); | 1362 | retval = bus_rescan_devices(intf->dev.bus); |
1353 | usb_lock_device(ps->dev); | 1363 | usb_lock_device(ps->dev); |
1354 | break; | 1364 | break; |
1355 | 1365 | ||
@@ -1413,7 +1423,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) | |||
1413 | */ | 1423 | */ |
1414 | static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 1424 | static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
1415 | { | 1425 | { |
1416 | struct dev_state *ps = (struct dev_state *)file->private_data; | 1426 | struct dev_state *ps = file->private_data; |
1417 | struct usb_device *dev = ps->dev; | 1427 | struct usb_device *dev = ps->dev; |
1418 | void __user *p = (void __user *)arg; | 1428 | void __user *p = (void __user *)arg; |
1419 | int ret = -ENOTTY; | 1429 | int ret = -ENOTTY; |
@@ -1421,7 +1431,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
1421 | if (!(file->f_mode & FMODE_WRITE)) | 1431 | if (!(file->f_mode & FMODE_WRITE)) |
1422 | return -EPERM; | 1432 | return -EPERM; |
1423 | usb_lock_device(dev); | 1433 | usb_lock_device(dev); |
1424 | if (!connected(dev)) { | 1434 | if (!connected(ps)) { |
1425 | usb_unlock_device(dev); | 1435 | usb_unlock_device(dev); |
1426 | return -ENODEV; | 1436 | return -ENODEV; |
1427 | } | 1437 | } |
@@ -1556,18 +1566,18 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
1556 | /* No kernel lock - fine */ | 1566 | /* No kernel lock - fine */ |
1557 | static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait) | 1567 | static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait) |
1558 | { | 1568 | { |
1559 | struct dev_state *ps = (struct dev_state *)file->private_data; | 1569 | struct dev_state *ps = file->private_data; |
1560 | unsigned int mask = 0; | 1570 | unsigned int mask = 0; |
1561 | 1571 | ||
1562 | poll_wait(file, &ps->wait, wait); | 1572 | poll_wait(file, &ps->wait, wait); |
1563 | if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) | 1573 | if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) |
1564 | mask |= POLLOUT | POLLWRNORM; | 1574 | mask |= POLLOUT | POLLWRNORM; |
1565 | if (!connected(ps->dev)) | 1575 | if (!connected(ps)) |
1566 | mask |= POLLERR | POLLHUP; | 1576 | mask |= POLLERR | POLLHUP; |
1567 | return mask; | 1577 | return mask; |
1568 | } | 1578 | } |
1569 | 1579 | ||
1570 | struct file_operations usbfs_device_file_operations = { | 1580 | const struct file_operations usbfs_device_file_operations = { |
1571 | .llseek = usbdev_lseek, | 1581 | .llseek = usbdev_lseek, |
1572 | .read = usbdev_read, | 1582 | .read = usbdev_read, |
1573 | .poll = usbdev_poll, | 1583 | .poll = usbdev_poll, |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ec8906501415..b10463244413 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -17,7 +17,8 @@ | |||
17 | * | 17 | * |
18 | * NOTE! This is not actually a driver at all, rather this is | 18 | * NOTE! This is not actually a driver at all, rather this is |
19 | * just a collection of helper routines that implement the | 19 | * just a collection of helper routines that implement the |
20 | * generic USB things that the real drivers can use.. | 20 | * matching, probing, releasing, suspending and resuming for |
21 | * real drivers. | ||
21 | * | 22 | * |
22 | */ | 23 | */ |
23 | 24 | ||
@@ -34,38 +35,6 @@ struct usb_dynid { | |||
34 | struct usb_device_id id; | 35 | struct usb_device_id id; |
35 | }; | 36 | }; |
36 | 37 | ||
37 | |||
38 | static int generic_probe(struct device *dev) | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
42 | static int generic_remove(struct device *dev) | ||
43 | { | ||
44 | struct usb_device *udev = to_usb_device(dev); | ||
45 | |||
46 | /* if this is only an unbind, not a physical disconnect, then | ||
47 | * unconfigure the device */ | ||
48 | if (udev->state == USB_STATE_CONFIGURED) | ||
49 | usb_set_configuration(udev, 0); | ||
50 | |||
51 | /* in case the call failed or the device was suspended */ | ||
52 | if (udev->state >= USB_STATE_CONFIGURED) | ||
53 | usb_disable_device(udev, 0); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | struct device_driver usb_generic_driver = { | ||
58 | .owner = THIS_MODULE, | ||
59 | .name = "usb", | ||
60 | .bus = &usb_bus_type, | ||
61 | .probe = generic_probe, | ||
62 | .remove = generic_remove, | ||
63 | }; | ||
64 | |||
65 | /* Fun hack to determine if the struct device is a | ||
66 | * usb device or a usb interface. */ | ||
67 | int usb_generic_driver_data; | ||
68 | |||
69 | #ifdef CONFIG_HOTPLUG | 38 | #ifdef CONFIG_HOTPLUG |
70 | 39 | ||
71 | /* | 40 | /* |
@@ -80,6 +49,7 @@ static ssize_t store_new_id(struct device_driver *driver, | |||
80 | u32 idVendor = 0; | 49 | u32 idVendor = 0; |
81 | u32 idProduct = 0; | 50 | u32 idProduct = 0; |
82 | int fields = 0; | 51 | int fields = 0; |
52 | int retval = 0; | ||
83 | 53 | ||
84 | fields = sscanf(buf, "%x %x", &idVendor, &idProduct); | 54 | fields = sscanf(buf, "%x %x", &idVendor, &idProduct); |
85 | if (fields < 2) | 55 | if (fields < 2) |
@@ -99,10 +69,12 @@ static ssize_t store_new_id(struct device_driver *driver, | |||
99 | spin_unlock(&usb_drv->dynids.lock); | 69 | spin_unlock(&usb_drv->dynids.lock); |
100 | 70 | ||
101 | if (get_driver(driver)) { | 71 | if (get_driver(driver)) { |
102 | driver_attach(driver); | 72 | retval = driver_attach(driver); |
103 | put_driver(driver); | 73 | put_driver(driver); |
104 | } | 74 | } |
105 | 75 | ||
76 | if (retval) | ||
77 | return retval; | ||
106 | return count; | 78 | return count; |
107 | } | 79 | } |
108 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | 80 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); |
@@ -115,7 +87,7 @@ static int usb_create_newid_file(struct usb_driver *usb_drv) | |||
115 | goto exit; | 87 | goto exit; |
116 | 88 | ||
117 | if (usb_drv->probe != NULL) | 89 | if (usb_drv->probe != NULL) |
118 | error = sysfs_create_file(&usb_drv->driver.kobj, | 90 | error = sysfs_create_file(&usb_drv->drvwrap.driver.kobj, |
119 | &driver_attr_new_id.attr); | 91 | &driver_attr_new_id.attr); |
120 | exit: | 92 | exit: |
121 | return error; | 93 | return error; |
@@ -127,7 +99,7 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv) | |||
127 | return; | 99 | return; |
128 | 100 | ||
129 | if (usb_drv->probe != NULL) | 101 | if (usb_drv->probe != NULL) |
130 | sysfs_remove_file(&usb_drv->driver.kobj, | 102 | sysfs_remove_file(&usb_drv->drvwrap.driver.kobj, |
131 | &driver_attr_new_id.attr); | 103 | &driver_attr_new_id.attr); |
132 | } | 104 | } |
133 | 105 | ||
@@ -174,21 +146,57 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in | |||
174 | } | 146 | } |
175 | 147 | ||
176 | 148 | ||
177 | /* called from driver core with usb_bus_type.subsys writelock */ | 149 | /* called from driver core with dev locked */ |
150 | static int usb_probe_device(struct device *dev) | ||
151 | { | ||
152 | struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); | ||
153 | struct usb_device *udev; | ||
154 | int error = -ENODEV; | ||
155 | |||
156 | dev_dbg(dev, "%s\n", __FUNCTION__); | ||
157 | |||
158 | if (!is_usb_device(dev)) /* Sanity check */ | ||
159 | return error; | ||
160 | |||
161 | udev = to_usb_device(dev); | ||
162 | |||
163 | /* TODO: Add real matching code */ | ||
164 | |||
165 | /* The device should always appear to be in use | ||
166 | * unless the driver suports autosuspend. | ||
167 | */ | ||
168 | udev->pm_usage_cnt = !(udriver->supports_autosuspend); | ||
169 | |||
170 | error = udriver->probe(udev); | ||
171 | return error; | ||
172 | } | ||
173 | |||
174 | /* called from driver core with dev locked */ | ||
175 | static int usb_unbind_device(struct device *dev) | ||
176 | { | ||
177 | struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); | ||
178 | |||
179 | udriver->disconnect(to_usb_device(dev)); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | |||
184 | /* called from driver core with dev locked */ | ||
178 | static int usb_probe_interface(struct device *dev) | 185 | static int usb_probe_interface(struct device *dev) |
179 | { | 186 | { |
180 | struct usb_interface * intf = to_usb_interface(dev); | 187 | struct usb_driver *driver = to_usb_driver(dev->driver); |
181 | struct usb_driver * driver = to_usb_driver(dev->driver); | 188 | struct usb_interface *intf; |
189 | struct usb_device *udev; | ||
182 | const struct usb_device_id *id; | 190 | const struct usb_device_id *id; |
183 | int error = -ENODEV; | 191 | int error = -ENODEV; |
184 | 192 | ||
185 | dev_dbg(dev, "%s\n", __FUNCTION__); | 193 | dev_dbg(dev, "%s\n", __FUNCTION__); |
186 | 194 | ||
187 | if (!driver->probe) | 195 | if (is_usb_device(dev)) /* Sanity check */ |
188 | return error; | 196 | return error; |
189 | /* FIXME we'd much prefer to just resume it ... */ | 197 | |
190 | if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) | 198 | intf = to_usb_interface(dev); |
191 | return -EHOSTUNREACH; | 199 | udev = interface_to_usbdev(intf); |
192 | 200 | ||
193 | id = usb_match_id(intf, driver->id_table); | 201 | id = usb_match_id(intf, driver->id_table); |
194 | if (!id) | 202 | if (!id) |
@@ -196,48 +204,165 @@ static int usb_probe_interface(struct device *dev) | |||
196 | if (id) { | 204 | if (id) { |
197 | dev_dbg(dev, "%s - got id\n", __FUNCTION__); | 205 | dev_dbg(dev, "%s - got id\n", __FUNCTION__); |
198 | 206 | ||
207 | error = usb_autoresume_device(udev, 1); | ||
208 | if (error) | ||
209 | return error; | ||
210 | |||
199 | /* Interface "power state" doesn't correspond to any hardware | 211 | /* Interface "power state" doesn't correspond to any hardware |
200 | * state whatsoever. We use it to record when it's bound to | 212 | * state whatsoever. We use it to record when it's bound to |
201 | * a driver that may start I/0: it's not frozen/quiesced. | 213 | * a driver that may start I/0: it's not frozen/quiesced. |
202 | */ | 214 | */ |
203 | mark_active(intf); | 215 | mark_active(intf); |
204 | intf->condition = USB_INTERFACE_BINDING; | 216 | intf->condition = USB_INTERFACE_BINDING; |
217 | |||
218 | /* The interface should always appear to be in use | ||
219 | * unless the driver suports autosuspend. | ||
220 | */ | ||
221 | intf->pm_usage_cnt = !(driver->supports_autosuspend); | ||
222 | |||
205 | error = driver->probe(intf, id); | 223 | error = driver->probe(intf, id); |
206 | if (error) { | 224 | if (error) { |
207 | mark_quiesced(intf); | 225 | mark_quiesced(intf); |
226 | intf->needs_remote_wakeup = 0; | ||
208 | intf->condition = USB_INTERFACE_UNBOUND; | 227 | intf->condition = USB_INTERFACE_UNBOUND; |
209 | } else | 228 | } else |
210 | intf->condition = USB_INTERFACE_BOUND; | 229 | intf->condition = USB_INTERFACE_BOUND; |
230 | |||
231 | usb_autosuspend_device(udev, 1); | ||
211 | } | 232 | } |
212 | 233 | ||
213 | return error; | 234 | return error; |
214 | } | 235 | } |
215 | 236 | ||
216 | /* called from driver core with usb_bus_type.subsys writelock */ | 237 | /* called from driver core with dev locked */ |
217 | static int usb_unbind_interface(struct device *dev) | 238 | static int usb_unbind_interface(struct device *dev) |
218 | { | 239 | { |
240 | struct usb_driver *driver = to_usb_driver(dev->driver); | ||
219 | struct usb_interface *intf = to_usb_interface(dev); | 241 | struct usb_interface *intf = to_usb_interface(dev); |
220 | struct usb_driver *driver = to_usb_driver(intf->dev.driver); | 242 | struct usb_device *udev; |
243 | int error; | ||
221 | 244 | ||
222 | intf->condition = USB_INTERFACE_UNBINDING; | 245 | intf->condition = USB_INTERFACE_UNBINDING; |
223 | 246 | ||
247 | /* Autoresume for set_interface call below */ | ||
248 | udev = interface_to_usbdev(intf); | ||
249 | error = usb_autoresume_device(udev, 1); | ||
250 | |||
224 | /* release all urbs for this interface */ | 251 | /* release all urbs for this interface */ |
225 | usb_disable_interface(interface_to_usbdev(intf), intf); | 252 | usb_disable_interface(interface_to_usbdev(intf), intf); |
226 | 253 | ||
227 | if (driver && driver->disconnect) | 254 | driver->disconnect(intf); |
228 | driver->disconnect(intf); | ||
229 | 255 | ||
230 | /* reset other interface state */ | 256 | /* reset other interface state */ |
231 | usb_set_interface(interface_to_usbdev(intf), | 257 | usb_set_interface(interface_to_usbdev(intf), |
232 | intf->altsetting[0].desc.bInterfaceNumber, | 258 | intf->altsetting[0].desc.bInterfaceNumber, |
233 | 0); | 259 | 0); |
234 | usb_set_intfdata(intf, NULL); | 260 | usb_set_intfdata(intf, NULL); |
261 | |||
235 | intf->condition = USB_INTERFACE_UNBOUND; | 262 | intf->condition = USB_INTERFACE_UNBOUND; |
236 | mark_quiesced(intf); | 263 | mark_quiesced(intf); |
264 | intf->needs_remote_wakeup = 0; | ||
265 | |||
266 | if (!error) | ||
267 | usb_autosuspend_device(udev, 1); | ||
237 | 268 | ||
238 | return 0; | 269 | return 0; |
239 | } | 270 | } |
240 | 271 | ||
272 | /** | ||
273 | * usb_driver_claim_interface - bind a driver to an interface | ||
274 | * @driver: the driver to be bound | ||
275 | * @iface: the interface to which it will be bound; must be in the | ||
276 | * usb device's active configuration | ||
277 | * @priv: driver data associated with that interface | ||
278 | * | ||
279 | * This is used by usb device drivers that need to claim more than one | ||
280 | * interface on a device when probing (audio and acm are current examples). | ||
281 | * No device driver should directly modify internal usb_interface or | ||
282 | * usb_device structure members. | ||
283 | * | ||
284 | * Few drivers should need to use this routine, since the most natural | ||
285 | * way to bind to an interface is to return the private data from | ||
286 | * the driver's probe() method. | ||
287 | * | ||
288 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
289 | * writelock. So driver probe() entries don't need extra locking, | ||
290 | * but other call contexts may need to explicitly claim those locks. | ||
291 | */ | ||
292 | int usb_driver_claim_interface(struct usb_driver *driver, | ||
293 | struct usb_interface *iface, void* priv) | ||
294 | { | ||
295 | struct device *dev = &iface->dev; | ||
296 | struct usb_device *udev = interface_to_usbdev(iface); | ||
297 | int retval = 0; | ||
298 | |||
299 | if (dev->driver) | ||
300 | return -EBUSY; | ||
301 | |||
302 | dev->driver = &driver->drvwrap.driver; | ||
303 | usb_set_intfdata(iface, priv); | ||
304 | |||
305 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
306 | iface->condition = USB_INTERFACE_BOUND; | ||
307 | mark_active(iface); | ||
308 | iface->pm_usage_cnt = !(driver->supports_autosuspend); | ||
309 | mutex_unlock(&udev->pm_mutex); | ||
310 | |||
311 | /* if interface was already added, bind now; else let | ||
312 | * the future device_add() bind it, bypassing probe() | ||
313 | */ | ||
314 | if (device_is_registered(dev)) | ||
315 | retval = device_bind_driver(dev); | ||
316 | |||
317 | return retval; | ||
318 | } | ||
319 | EXPORT_SYMBOL(usb_driver_claim_interface); | ||
320 | |||
321 | /** | ||
322 | * usb_driver_release_interface - unbind a driver from an interface | ||
323 | * @driver: the driver to be unbound | ||
324 | * @iface: the interface from which it will be unbound | ||
325 | * | ||
326 | * This can be used by drivers to release an interface without waiting | ||
327 | * for their disconnect() methods to be called. In typical cases this | ||
328 | * also causes the driver disconnect() method to be called. | ||
329 | * | ||
330 | * This call is synchronous, and may not be used in an interrupt context. | ||
331 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
332 | * writelock. So driver disconnect() entries don't need extra locking, | ||
333 | * but other call contexts may need to explicitly claim those locks. | ||
334 | */ | ||
335 | void usb_driver_release_interface(struct usb_driver *driver, | ||
336 | struct usb_interface *iface) | ||
337 | { | ||
338 | struct device *dev = &iface->dev; | ||
339 | struct usb_device *udev = interface_to_usbdev(iface); | ||
340 | |||
341 | /* this should never happen, don't release something that's not ours */ | ||
342 | if (!dev->driver || dev->driver != &driver->drvwrap.driver) | ||
343 | return; | ||
344 | |||
345 | /* don't release from within disconnect() */ | ||
346 | if (iface->condition != USB_INTERFACE_BOUND) | ||
347 | return; | ||
348 | |||
349 | /* don't release if the interface hasn't been added yet */ | ||
350 | if (device_is_registered(dev)) { | ||
351 | iface->condition = USB_INTERFACE_UNBINDING; | ||
352 | device_release_driver(dev); | ||
353 | } | ||
354 | |||
355 | dev->driver = NULL; | ||
356 | usb_set_intfdata(iface, NULL); | ||
357 | |||
358 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
359 | iface->condition = USB_INTERFACE_UNBOUND; | ||
360 | mark_quiesced(iface); | ||
361 | iface->needs_remote_wakeup = 0; | ||
362 | mutex_unlock(&udev->pm_mutex); | ||
363 | } | ||
364 | EXPORT_SYMBOL(usb_driver_release_interface); | ||
365 | |||
241 | /* returns 0 if no match, 1 if match */ | 366 | /* returns 0 if no match, 1 if match */ |
242 | static int usb_match_one_id(struct usb_interface *interface, | 367 | static int usb_match_one_id(struct usb_interface *interface, |
243 | const struct usb_device_id *id) | 368 | const struct usb_device_id *id) |
@@ -381,35 +506,223 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_match_id); | |||
381 | 506 | ||
382 | int usb_device_match(struct device *dev, struct device_driver *drv) | 507 | int usb_device_match(struct device *dev, struct device_driver *drv) |
383 | { | 508 | { |
509 | /* devices and interfaces are handled separately */ | ||
510 | if (is_usb_device(dev)) { | ||
511 | |||
512 | /* interface drivers never match devices */ | ||
513 | if (!is_usb_device_driver(drv)) | ||
514 | return 0; | ||
515 | |||
516 | /* TODO: Add real matching code */ | ||
517 | return 1; | ||
518 | |||
519 | } else { | ||
520 | struct usb_interface *intf; | ||
521 | struct usb_driver *usb_drv; | ||
522 | const struct usb_device_id *id; | ||
523 | |||
524 | /* device drivers never match interfaces */ | ||
525 | if (is_usb_device_driver(drv)) | ||
526 | return 0; | ||
527 | |||
528 | intf = to_usb_interface(dev); | ||
529 | usb_drv = to_usb_driver(drv); | ||
530 | |||
531 | id = usb_match_id(intf, usb_drv->id_table); | ||
532 | if (id) | ||
533 | return 1; | ||
534 | |||
535 | id = usb_match_dynamic_id(intf, usb_drv); | ||
536 | if (id) | ||
537 | return 1; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | #ifdef CONFIG_HOTPLUG | ||
544 | |||
545 | /* | ||
546 | * This sends an uevent to userspace, typically helping to load driver | ||
547 | * or other modules, configure the device, and more. Drivers can provide | ||
548 | * a MODULE_DEVICE_TABLE to help with module loading subtasks. | ||
549 | * | ||
550 | * We're called either from khubd (the typical case) or from root hub | ||
551 | * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle | ||
552 | * delays in event delivery. Use sysfs (and DEVPATH) to make sure the | ||
553 | * device (and this configuration!) are still present. | ||
554 | */ | ||
555 | static int usb_uevent(struct device *dev, char **envp, int num_envp, | ||
556 | char *buffer, int buffer_size) | ||
557 | { | ||
384 | struct usb_interface *intf; | 558 | struct usb_interface *intf; |
385 | struct usb_driver *usb_drv; | 559 | struct usb_device *usb_dev; |
386 | const struct usb_device_id *id; | 560 | struct usb_host_interface *alt; |
561 | int i = 0; | ||
562 | int length = 0; | ||
387 | 563 | ||
388 | /* check for generic driver, which we don't match any device with */ | 564 | if (!dev) |
389 | if (drv == &usb_generic_driver) | 565 | return -ENODEV; |
390 | return 0; | ||
391 | 566 | ||
392 | intf = to_usb_interface(dev); | 567 | /* driver is often null here; dev_dbg() would oops */ |
393 | usb_drv = to_usb_driver(drv); | 568 | pr_debug ("usb %s: uevent\n", dev->bus_id); |
394 | 569 | ||
395 | id = usb_match_id(intf, usb_drv->id_table); | 570 | if (is_usb_device(dev)) { |
396 | if (id) | 571 | usb_dev = to_usb_device(dev); |
397 | return 1; | 572 | alt = NULL; |
573 | } else { | ||
574 | intf = to_usb_interface(dev); | ||
575 | usb_dev = interface_to_usbdev(intf); | ||
576 | alt = intf->cur_altsetting; | ||
577 | } | ||
578 | |||
579 | if (usb_dev->devnum < 0) { | ||
580 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); | ||
581 | return -ENODEV; | ||
582 | } | ||
583 | if (!usb_dev->bus) { | ||
584 | pr_debug ("usb %s: bus removed?\n", dev->bus_id); | ||
585 | return -ENODEV; | ||
586 | } | ||
587 | |||
588 | #ifdef CONFIG_USB_DEVICEFS | ||
589 | /* If this is available, userspace programs can directly read | ||
590 | * all the device descriptors we don't tell them about. Or | ||
591 | * even act as usermode drivers. | ||
592 | * | ||
593 | * FIXME reduce hardwired intelligence here | ||
594 | */ | ||
595 | if (add_uevent_var(envp, num_envp, &i, | ||
596 | buffer, buffer_size, &length, | ||
597 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
598 | usb_dev->bus->busnum, usb_dev->devnum)) | ||
599 | return -ENOMEM; | ||
600 | #endif | ||
601 | |||
602 | /* per-device configurations are common */ | ||
603 | if (add_uevent_var(envp, num_envp, &i, | ||
604 | buffer, buffer_size, &length, | ||
605 | "PRODUCT=%x/%x/%x", | ||
606 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
607 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
608 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | ||
609 | return -ENOMEM; | ||
610 | |||
611 | /* class-based driver binding models */ | ||
612 | if (add_uevent_var(envp, num_envp, &i, | ||
613 | buffer, buffer_size, &length, | ||
614 | "TYPE=%d/%d/%d", | ||
615 | usb_dev->descriptor.bDeviceClass, | ||
616 | usb_dev->descriptor.bDeviceSubClass, | ||
617 | usb_dev->descriptor.bDeviceProtocol)) | ||
618 | return -ENOMEM; | ||
619 | |||
620 | if (!is_usb_device(dev)) { | ||
621 | |||
622 | if (add_uevent_var(envp, num_envp, &i, | ||
623 | buffer, buffer_size, &length, | ||
624 | "INTERFACE=%d/%d/%d", | ||
625 | alt->desc.bInterfaceClass, | ||
626 | alt->desc.bInterfaceSubClass, | ||
627 | alt->desc.bInterfaceProtocol)) | ||
628 | return -ENOMEM; | ||
629 | |||
630 | if (add_uevent_var(envp, num_envp, &i, | ||
631 | buffer, buffer_size, &length, | ||
632 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | ||
633 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
634 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
635 | le16_to_cpu(usb_dev->descriptor.bcdDevice), | ||
636 | usb_dev->descriptor.bDeviceClass, | ||
637 | usb_dev->descriptor.bDeviceSubClass, | ||
638 | usb_dev->descriptor.bDeviceProtocol, | ||
639 | alt->desc.bInterfaceClass, | ||
640 | alt->desc.bInterfaceSubClass, | ||
641 | alt->desc.bInterfaceProtocol)) | ||
642 | return -ENOMEM; | ||
643 | } | ||
644 | |||
645 | envp[i] = NULL; | ||
398 | 646 | ||
399 | id = usb_match_dynamic_id(intf, usb_drv); | ||
400 | if (id) | ||
401 | return 1; | ||
402 | return 0; | 647 | return 0; |
403 | } | 648 | } |
404 | 649 | ||
650 | #else | ||
651 | |||
652 | static int usb_uevent(struct device *dev, char **envp, | ||
653 | int num_envp, char *buffer, int buffer_size) | ||
654 | { | ||
655 | return -ENODEV; | ||
656 | } | ||
657 | |||
658 | #endif /* CONFIG_HOTPLUG */ | ||
659 | |||
660 | /** | ||
661 | * usb_register_device_driver - register a USB device (not interface) driver | ||
662 | * @new_udriver: USB operations for the device driver | ||
663 | * @owner: module owner of this driver. | ||
664 | * | ||
665 | * Registers a USB device driver with the USB core. The list of | ||
666 | * unattached devices will be rescanned whenever a new driver is | ||
667 | * added, allowing the new driver to attach to any recognized devices. | ||
668 | * Returns a negative error code on failure and 0 on success. | ||
669 | */ | ||
670 | int usb_register_device_driver(struct usb_device_driver *new_udriver, | ||
671 | struct module *owner) | ||
672 | { | ||
673 | int retval = 0; | ||
674 | |||
675 | if (usb_disabled()) | ||
676 | return -ENODEV; | ||
677 | |||
678 | new_udriver->drvwrap.for_devices = 1; | ||
679 | new_udriver->drvwrap.driver.name = (char *) new_udriver->name; | ||
680 | new_udriver->drvwrap.driver.bus = &usb_bus_type; | ||
681 | new_udriver->drvwrap.driver.probe = usb_probe_device; | ||
682 | new_udriver->drvwrap.driver.remove = usb_unbind_device; | ||
683 | new_udriver->drvwrap.driver.owner = owner; | ||
684 | |||
685 | retval = driver_register(&new_udriver->drvwrap.driver); | ||
686 | |||
687 | if (!retval) { | ||
688 | pr_info("%s: registered new device driver %s\n", | ||
689 | usbcore_name, new_udriver->name); | ||
690 | usbfs_update_special(); | ||
691 | } else { | ||
692 | printk(KERN_ERR "%s: error %d registering device " | ||
693 | " driver %s\n", | ||
694 | usbcore_name, retval, new_udriver->name); | ||
695 | } | ||
696 | |||
697 | return retval; | ||
698 | } | ||
699 | EXPORT_SYMBOL_GPL(usb_register_device_driver); | ||
700 | |||
701 | /** | ||
702 | * usb_deregister_device_driver - unregister a USB device (not interface) driver | ||
703 | * @udriver: USB operations of the device driver to unregister | ||
704 | * Context: must be able to sleep | ||
705 | * | ||
706 | * Unlinks the specified driver from the internal USB driver list. | ||
707 | */ | ||
708 | void usb_deregister_device_driver(struct usb_device_driver *udriver) | ||
709 | { | ||
710 | pr_info("%s: deregistering device driver %s\n", | ||
711 | usbcore_name, udriver->name); | ||
712 | |||
713 | driver_unregister(&udriver->drvwrap.driver); | ||
714 | usbfs_update_special(); | ||
715 | } | ||
716 | EXPORT_SYMBOL_GPL(usb_deregister_device_driver); | ||
717 | |||
405 | /** | 718 | /** |
406 | * usb_register_driver - register a USB driver | 719 | * usb_register_driver - register a USB interface driver |
407 | * @new_driver: USB operations for the driver | 720 | * @new_driver: USB operations for the interface driver |
408 | * @owner: module owner of this driver. | 721 | * @owner: module owner of this driver. |
409 | * | 722 | * |
410 | * Registers a USB driver with the USB core. The list of unattached | 723 | * Registers a USB interface driver with the USB core. The list of |
411 | * interfaces will be rescanned whenever a new driver is added, allowing | 724 | * unattached interfaces will be rescanned whenever a new driver is |
412 | * the new driver to attach to any recognized devices. | 725 | * added, allowing the new driver to attach to any recognized interfaces. |
413 | * Returns a negative error code on failure and 0 on success. | 726 | * Returns a negative error code on failure and 0 on success. |
414 | * | 727 | * |
415 | * NOTE: if you want your driver to use the USB major number, you must call | 728 | * NOTE: if you want your driver to use the USB major number, you must call |
@@ -423,23 +736,25 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) | |||
423 | if (usb_disabled()) | 736 | if (usb_disabled()) |
424 | return -ENODEV; | 737 | return -ENODEV; |
425 | 738 | ||
426 | new_driver->driver.name = (char *)new_driver->name; | 739 | new_driver->drvwrap.for_devices = 0; |
427 | new_driver->driver.bus = &usb_bus_type; | 740 | new_driver->drvwrap.driver.name = (char *) new_driver->name; |
428 | new_driver->driver.probe = usb_probe_interface; | 741 | new_driver->drvwrap.driver.bus = &usb_bus_type; |
429 | new_driver->driver.remove = usb_unbind_interface; | 742 | new_driver->drvwrap.driver.probe = usb_probe_interface; |
430 | new_driver->driver.owner = owner; | 743 | new_driver->drvwrap.driver.remove = usb_unbind_interface; |
744 | new_driver->drvwrap.driver.owner = owner; | ||
431 | spin_lock_init(&new_driver->dynids.lock); | 745 | spin_lock_init(&new_driver->dynids.lock); |
432 | INIT_LIST_HEAD(&new_driver->dynids.list); | 746 | INIT_LIST_HEAD(&new_driver->dynids.list); |
433 | 747 | ||
434 | retval = driver_register(&new_driver->driver); | 748 | retval = driver_register(&new_driver->drvwrap.driver); |
435 | 749 | ||
436 | if (!retval) { | 750 | if (!retval) { |
437 | pr_info("%s: registered new driver %s\n", | 751 | pr_info("%s: registered new interface driver %s\n", |
438 | usbcore_name, new_driver->name); | 752 | usbcore_name, new_driver->name); |
439 | usbfs_update_special(); | 753 | usbfs_update_special(); |
440 | usb_create_newid_file(new_driver); | 754 | usb_create_newid_file(new_driver); |
441 | } else { | 755 | } else { |
442 | printk(KERN_ERR "%s: error %d registering driver %s\n", | 756 | printk(KERN_ERR "%s: error %d registering interface " |
757 | " driver %s\n", | ||
443 | usbcore_name, retval, new_driver->name); | 758 | usbcore_name, retval, new_driver->name); |
444 | } | 759 | } |
445 | 760 | ||
@@ -448,8 +763,8 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) | |||
448 | EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); | 763 | EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); |
449 | 764 | ||
450 | /** | 765 | /** |
451 | * usb_deregister - unregister a USB driver | 766 | * usb_deregister - unregister a USB interface driver |
452 | * @driver: USB operations of the driver to unregister | 767 | * @driver: USB operations of the interface driver to unregister |
453 | * Context: must be able to sleep | 768 | * Context: must be able to sleep |
454 | * | 769 | * |
455 | * Unlinks the specified driver from the internal USB driver list. | 770 | * Unlinks the specified driver from the internal USB driver list. |
@@ -460,12 +775,554 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); | |||
460 | */ | 775 | */ |
461 | void usb_deregister(struct usb_driver *driver) | 776 | void usb_deregister(struct usb_driver *driver) |
462 | { | 777 | { |
463 | pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); | 778 | pr_info("%s: deregistering interface driver %s\n", |
779 | usbcore_name, driver->name); | ||
464 | 780 | ||
465 | usb_remove_newid_file(driver); | 781 | usb_remove_newid_file(driver); |
466 | usb_free_dynids(driver); | 782 | usb_free_dynids(driver); |
467 | driver_unregister(&driver->driver); | 783 | driver_unregister(&driver->drvwrap.driver); |
468 | 784 | ||
469 | usbfs_update_special(); | 785 | usbfs_update_special(); |
470 | } | 786 | } |
471 | EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); | 787 | EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); |
788 | |||
789 | #ifdef CONFIG_PM | ||
790 | |||
791 | /* Caller has locked udev->pm_mutex */ | ||
792 | static int suspend_device(struct usb_device *udev, pm_message_t msg) | ||
793 | { | ||
794 | struct usb_device_driver *udriver; | ||
795 | int status = 0; | ||
796 | |||
797 | if (udev->state == USB_STATE_NOTATTACHED || | ||
798 | udev->state == USB_STATE_SUSPENDED) | ||
799 | goto done; | ||
800 | |||
801 | /* For devices that don't have a driver, we do a standard suspend. */ | ||
802 | if (udev->dev.driver == NULL) { | ||
803 | udev->do_remote_wakeup = 0; | ||
804 | status = usb_port_suspend(udev); | ||
805 | goto done; | ||
806 | } | ||
807 | |||
808 | udriver = to_usb_device_driver(udev->dev.driver); | ||
809 | status = udriver->suspend(udev, msg); | ||
810 | |||
811 | done: | ||
812 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | ||
813 | if (status == 0) | ||
814 | udev->dev.power.power_state.event = msg.event; | ||
815 | return status; | ||
816 | } | ||
817 | |||
818 | /* Caller has locked udev->pm_mutex */ | ||
819 | static int resume_device(struct usb_device *udev) | ||
820 | { | ||
821 | struct usb_device_driver *udriver; | ||
822 | int status = 0; | ||
823 | |||
824 | if (udev->state == USB_STATE_NOTATTACHED || | ||
825 | udev->state != USB_STATE_SUSPENDED) | ||
826 | goto done; | ||
827 | |||
828 | /* Can't resume it if it doesn't have a driver. */ | ||
829 | if (udev->dev.driver == NULL) { | ||
830 | status = -ENOTCONN; | ||
831 | goto done; | ||
832 | } | ||
833 | |||
834 | udriver = to_usb_device_driver(udev->dev.driver); | ||
835 | status = udriver->resume(udev); | ||
836 | |||
837 | done: | ||
838 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | ||
839 | if (status == 0) | ||
840 | udev->dev.power.power_state.event = PM_EVENT_ON; | ||
841 | return status; | ||
842 | } | ||
843 | |||
844 | /* Caller has locked intf's usb_device's pm_mutex */ | ||
845 | static int suspend_interface(struct usb_interface *intf, pm_message_t msg) | ||
846 | { | ||
847 | struct usb_driver *driver; | ||
848 | int status = 0; | ||
849 | |||
850 | /* with no hardware, USB interfaces only use FREEZE and ON states */ | ||
851 | if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || | ||
852 | !is_active(intf)) | ||
853 | goto done; | ||
854 | |||
855 | if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */ | ||
856 | goto done; | ||
857 | driver = to_usb_driver(intf->dev.driver); | ||
858 | |||
859 | if (driver->suspend && driver->resume) { | ||
860 | status = driver->suspend(intf, msg); | ||
861 | if (status == 0) | ||
862 | mark_quiesced(intf); | ||
863 | else if (!interface_to_usbdev(intf)->auto_pm) | ||
864 | dev_err(&intf->dev, "%s error %d\n", | ||
865 | "suspend", status); | ||
866 | } else { | ||
867 | // FIXME else if there's no suspend method, disconnect... | ||
868 | // Not possible if auto_pm is set... | ||
869 | dev_warn(&intf->dev, "no suspend for driver %s?\n", | ||
870 | driver->name); | ||
871 | mark_quiesced(intf); | ||
872 | } | ||
873 | |||
874 | done: | ||
875 | // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); | ||
876 | if (status == 0) | ||
877 | intf->dev.power.power_state.event = msg.event; | ||
878 | return status; | ||
879 | } | ||
880 | |||
881 | /* Caller has locked intf's usb_device's pm_mutex */ | ||
882 | static int resume_interface(struct usb_interface *intf) | ||
883 | { | ||
884 | struct usb_driver *driver; | ||
885 | int status = 0; | ||
886 | |||
887 | if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || | ||
888 | is_active(intf)) | ||
889 | goto done; | ||
890 | |||
891 | /* Don't let autoresume interfere with unbinding */ | ||
892 | if (intf->condition == USB_INTERFACE_UNBINDING) | ||
893 | goto done; | ||
894 | |||
895 | /* Can't resume it if it doesn't have a driver. */ | ||
896 | if (intf->condition == USB_INTERFACE_UNBOUND) { | ||
897 | status = -ENOTCONN; | ||
898 | goto done; | ||
899 | } | ||
900 | driver = to_usb_driver(intf->dev.driver); | ||
901 | |||
902 | if (driver->resume) { | ||
903 | status = driver->resume(intf); | ||
904 | if (status) | ||
905 | dev_err(&intf->dev, "%s error %d\n", | ||
906 | "resume", status); | ||
907 | else | ||
908 | mark_active(intf); | ||
909 | } else { | ||
910 | dev_warn(&intf->dev, "no resume for driver %s?\n", | ||
911 | driver->name); | ||
912 | mark_active(intf); | ||
913 | } | ||
914 | |||
915 | done: | ||
916 | // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); | ||
917 | if (status == 0) | ||
918 | intf->dev.power.power_state.event = PM_EVENT_ON; | ||
919 | return status; | ||
920 | } | ||
921 | |||
922 | /** | ||
923 | * usb_suspend_both - suspend a USB device and its interfaces | ||
924 | * @udev: the usb_device to suspend | ||
925 | * @msg: Power Management message describing this state transition | ||
926 | * | ||
927 | * This is the central routine for suspending USB devices. It calls the | ||
928 | * suspend methods for all the interface drivers in @udev and then calls | ||
929 | * the suspend method for @udev itself. If an error occurs at any stage, | ||
930 | * all the interfaces which were suspended are resumed so that they remain | ||
931 | * in the same state as the device. | ||
932 | * | ||
933 | * If an autosuspend is in progress (@udev->auto_pm is set), the routine | ||
934 | * checks first to make sure that neither the device itself or any of its | ||
935 | * active interfaces is in use (pm_usage_cnt is greater than 0). If they | ||
936 | * are, the autosuspend fails. | ||
937 | * | ||
938 | * If the suspend succeeds, the routine recursively queues an autosuspend | ||
939 | * request for @udev's parent device, thereby propagating the change up | ||
940 | * the device tree. If all of the parent's children are now suspended, | ||
941 | * the parent will autosuspend in turn. | ||
942 | * | ||
943 | * The suspend method calls are subject to mutual exclusion under control | ||
944 | * of @udev's pm_mutex. Many of these calls are also under the protection | ||
945 | * of @udev's device lock (including all requests originating outside the | ||
946 | * USB subsystem), but autosuspend requests generated by a child device or | ||
947 | * interface driver may not be. Usbcore will insure that the method calls | ||
948 | * do not arrive during bind, unbind, or reset operations. However, drivers | ||
949 | * must be prepared to handle suspend calls arriving at unpredictable times. | ||
950 | * The only way to block such calls is to do an autoresume (preventing | ||
951 | * autosuspends) while holding @udev's device lock (preventing outside | ||
952 | * suspends). | ||
953 | * | ||
954 | * The caller must hold @udev->pm_mutex. | ||
955 | * | ||
956 | * This routine can run only in process context. | ||
957 | */ | ||
958 | int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | ||
959 | { | ||
960 | int status = 0; | ||
961 | int i = 0; | ||
962 | struct usb_interface *intf; | ||
963 | struct usb_device *parent = udev->parent; | ||
964 | |||
965 | cancel_delayed_work(&udev->autosuspend); | ||
966 | if (udev->state == USB_STATE_NOTATTACHED) | ||
967 | return 0; | ||
968 | if (udev->state == USB_STATE_SUSPENDED) | ||
969 | return 0; | ||
970 | |||
971 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | ||
972 | |||
973 | /* For autosuspend, fail fast if anything is in use. | ||
974 | * Also fail if any interfaces require remote wakeup but it | ||
975 | * isn't available. */ | ||
976 | if (udev->auto_pm) { | ||
977 | if (udev->pm_usage_cnt > 0) | ||
978 | return -EBUSY; | ||
979 | if (udev->actconfig) { | ||
980 | for (; i < udev->actconfig->desc.bNumInterfaces; i++) { | ||
981 | intf = udev->actconfig->interface[i]; | ||
982 | if (!is_active(intf)) | ||
983 | continue; | ||
984 | if (intf->pm_usage_cnt > 0) | ||
985 | return -EBUSY; | ||
986 | if (intf->needs_remote_wakeup && | ||
987 | !udev->do_remote_wakeup) { | ||
988 | dev_dbg(&udev->dev, | ||
989 | "remote wakeup needed for autosuspend\n"); | ||
990 | return -EOPNOTSUPP; | ||
991 | } | ||
992 | } | ||
993 | i = 0; | ||
994 | } | ||
995 | } | ||
996 | |||
997 | /* Suspend all the interfaces and then udev itself */ | ||
998 | if (udev->actconfig) { | ||
999 | for (; i < udev->actconfig->desc.bNumInterfaces; i++) { | ||
1000 | intf = udev->actconfig->interface[i]; | ||
1001 | status = suspend_interface(intf, msg); | ||
1002 | if (status != 0) | ||
1003 | break; | ||
1004 | } | ||
1005 | } | ||
1006 | if (status == 0) | ||
1007 | status = suspend_device(udev, msg); | ||
1008 | |||
1009 | /* If the suspend failed, resume interfaces that did get suspended */ | ||
1010 | if (status != 0) { | ||
1011 | while (--i >= 0) { | ||
1012 | intf = udev->actconfig->interface[i]; | ||
1013 | resume_interface(intf); | ||
1014 | } | ||
1015 | |||
1016 | /* If the suspend succeeded, propagate it up the tree */ | ||
1017 | } else if (parent) | ||
1018 | usb_autosuspend_device(parent, 0); | ||
1019 | |||
1020 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | ||
1021 | return status; | ||
1022 | } | ||
1023 | |||
1024 | /** | ||
1025 | * usb_resume_both - resume a USB device and its interfaces | ||
1026 | * @udev: the usb_device to resume | ||
1027 | * | ||
1028 | * This is the central routine for resuming USB devices. It calls the | ||
1029 | * the resume method for @udev and then calls the resume methods for all | ||
1030 | * the interface drivers in @udev. | ||
1031 | * | ||
1032 | * Before starting the resume, the routine calls itself recursively for | ||
1033 | * the parent device of @udev, thereby propagating the change up the device | ||
1034 | * tree and assuring that @udev will be able to resume. If the parent is | ||
1035 | * unable to resume successfully, the routine fails. | ||
1036 | * | ||
1037 | * The resume method calls are subject to mutual exclusion under control | ||
1038 | * of @udev's pm_mutex. Many of these calls are also under the protection | ||
1039 | * of @udev's device lock (including all requests originating outside the | ||
1040 | * USB subsystem), but autoresume requests generated by a child device or | ||
1041 | * interface driver may not be. Usbcore will insure that the method calls | ||
1042 | * do not arrive during bind, unbind, or reset operations. However, drivers | ||
1043 | * must be prepared to handle resume calls arriving at unpredictable times. | ||
1044 | * The only way to block such calls is to do an autoresume (preventing | ||
1045 | * other autoresumes) while holding @udev's device lock (preventing outside | ||
1046 | * resumes). | ||
1047 | * | ||
1048 | * The caller must hold @udev->pm_mutex. | ||
1049 | * | ||
1050 | * This routine can run only in process context. | ||
1051 | */ | ||
1052 | int usb_resume_both(struct usb_device *udev) | ||
1053 | { | ||
1054 | int status = 0; | ||
1055 | int i; | ||
1056 | struct usb_interface *intf; | ||
1057 | struct usb_device *parent = udev->parent; | ||
1058 | |||
1059 | cancel_delayed_work(&udev->autosuspend); | ||
1060 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1061 | return -ENODEV; | ||
1062 | |||
1063 | /* Propagate the resume up the tree, if necessary */ | ||
1064 | if (udev->state == USB_STATE_SUSPENDED) { | ||
1065 | if (parent) { | ||
1066 | mutex_lock_nested(&parent->pm_mutex, parent->level); | ||
1067 | parent->auto_pm = 1; | ||
1068 | status = usb_resume_both(parent); | ||
1069 | } else { | ||
1070 | |||
1071 | /* We can't progagate beyond the USB subsystem, | ||
1072 | * so if a root hub's controller is suspended | ||
1073 | * then we're stuck. */ | ||
1074 | if (udev->dev.parent->power.power_state.event != | ||
1075 | PM_EVENT_ON) | ||
1076 | status = -EHOSTUNREACH; | ||
1077 | } | ||
1078 | if (status == 0) | ||
1079 | status = resume_device(udev); | ||
1080 | if (parent) | ||
1081 | mutex_unlock(&parent->pm_mutex); | ||
1082 | } else { | ||
1083 | |||
1084 | /* Needed only for setting udev->dev.power.power_state.event | ||
1085 | * and for possible debugging message. */ | ||
1086 | status = resume_device(udev); | ||
1087 | } | ||
1088 | |||
1089 | /* Now the parent won't suspend until we are finished */ | ||
1090 | |||
1091 | if (status == 0 && udev->actconfig) { | ||
1092 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | ||
1093 | intf = udev->actconfig->interface[i]; | ||
1094 | resume_interface(intf); | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1098 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | ||
1099 | return status; | ||
1100 | } | ||
1101 | |||
1102 | #ifdef CONFIG_USB_SUSPEND | ||
1103 | |||
1104 | /** | ||
1105 | * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces | ||
1106 | * @udev - the usb_device to autosuspend | ||
1107 | * @dec_usage_cnt - flag to decrement @udev's PM-usage counter | ||
1108 | * | ||
1109 | * This routine should be called when a core subsystem is finished using | ||
1110 | * @udev and wants to allow it to autosuspend. Examples would be when | ||
1111 | * @udev's device file in usbfs is closed or after a configuration change. | ||
1112 | * | ||
1113 | * @dec_usage_cnt should be 1 if the subsystem previously incremented | ||
1114 | * @udev's usage counter (such as by passing 1 to usb_autoresume_device); | ||
1115 | * otherwise it should be 0. | ||
1116 | * | ||
1117 | * If the usage counter for @udev or any of its active interfaces is greater | ||
1118 | * than 0, the autosuspend request will not be queued. (If an interface | ||
1119 | * driver does not support autosuspend then its usage counter is permanently | ||
1120 | * positive.) Likewise, if an interface driver requires remote-wakeup | ||
1121 | * capability during autosuspend but remote wakeup is disabled, the | ||
1122 | * autosuspend will fail. | ||
1123 | * | ||
1124 | * Often the caller will hold @udev's device lock, but this is not | ||
1125 | * necessary. | ||
1126 | * | ||
1127 | * This routine can run only in process context. | ||
1128 | */ | ||
1129 | void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt) | ||
1130 | { | ||
1131 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
1132 | udev->pm_usage_cnt -= dec_usage_cnt; | ||
1133 | if (udev->pm_usage_cnt <= 0) | ||
1134 | schedule_delayed_work(&udev->autosuspend, | ||
1135 | USB_AUTOSUSPEND_DELAY); | ||
1136 | mutex_unlock(&udev->pm_mutex); | ||
1137 | // dev_dbg(&udev->dev, "%s: cnt %d\n", | ||
1138 | // __FUNCTION__, udev->pm_usage_cnt); | ||
1139 | } | ||
1140 | |||
1141 | /** | ||
1142 | * usb_autoresume_device - immediately autoresume a USB device and its interfaces | ||
1143 | * @udev - the usb_device to autoresume | ||
1144 | * @inc_usage_cnt - flag to increment @udev's PM-usage counter | ||
1145 | * | ||
1146 | * This routine should be called when a core subsystem wants to use @udev | ||
1147 | * and needs to guarantee that it is not suspended. In addition, the | ||
1148 | * caller can prevent @udev from being autosuspended subsequently. (Note | ||
1149 | * that this will not prevent suspend events originating in the PM core.) | ||
1150 | * Examples would be when @udev's device file in usbfs is opened (autosuspend | ||
1151 | * should be prevented until the file is closed) or when a remote-wakeup | ||
1152 | * request is received (later autosuspends should not be prevented). | ||
1153 | * | ||
1154 | * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent | ||
1155 | * autosuspends. This prevention will persist until the usage counter is | ||
1156 | * decremented again (such as by passing 1 to usb_autosuspend_device). | ||
1157 | * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged. | ||
1158 | * Regardless, if the autoresume fails then the usage counter is not | ||
1159 | * incremented. | ||
1160 | * | ||
1161 | * Often the caller will hold @udev's device lock, but this is not | ||
1162 | * necessary (and attempting it might cause deadlock). | ||
1163 | * | ||
1164 | * This routine can run only in process context. | ||
1165 | */ | ||
1166 | int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt) | ||
1167 | { | ||
1168 | int status; | ||
1169 | |||
1170 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
1171 | udev->pm_usage_cnt += inc_usage_cnt; | ||
1172 | udev->auto_pm = 1; | ||
1173 | status = usb_resume_both(udev); | ||
1174 | if (status != 0) | ||
1175 | udev->pm_usage_cnt -= inc_usage_cnt; | ||
1176 | mutex_unlock(&udev->pm_mutex); | ||
1177 | // dev_dbg(&udev->dev, "%s: status %d cnt %d\n", | ||
1178 | // __FUNCTION__, status, udev->pm_usage_cnt); | ||
1179 | return status; | ||
1180 | } | ||
1181 | |||
1182 | /** | ||
1183 | * usb_autopm_put_interface - decrement a USB interface's PM-usage counter | ||
1184 | * @intf - the usb_interface whose counter should be decremented | ||
1185 | * | ||
1186 | * This routine should be called by an interface driver when it is | ||
1187 | * finished using @intf and wants to allow it to autosuspend. A typical | ||
1188 | * example would be a character-device driver when its device file is | ||
1189 | * closed. | ||
1190 | * | ||
1191 | * The routine decrements @intf's usage counter. When the counter reaches | ||
1192 | * 0, a delayed autosuspend request for @intf's device is queued. When | ||
1193 | * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all | ||
1194 | * the other usage counters for the sibling interfaces and @intf's | ||
1195 | * usb_device, the device and all its interfaces will be autosuspended. | ||
1196 | * | ||
1197 | * Note that @intf->pm_usage_cnt is owned by the interface driver. The | ||
1198 | * core will not change its value other than the increment and decrement | ||
1199 | * in usb_autopm_get_interface and usb_autopm_put_interface. The driver | ||
1200 | * may use this simple counter-oriented discipline or may set the value | ||
1201 | * any way it likes. | ||
1202 | * | ||
1203 | * If the driver has set @intf->needs_remote_wakeup then autosuspend will | ||
1204 | * take place only if the device's remote-wakeup facility is enabled. | ||
1205 | * | ||
1206 | * Suspend method calls queued by this routine can arrive at any time | ||
1207 | * while @intf is resumed and its usage counter is equal to 0. They are | ||
1208 | * not protected by the usb_device's lock but only by its pm_mutex. | ||
1209 | * Drivers must provide their own synchronization. | ||
1210 | * | ||
1211 | * This routine can run only in process context. | ||
1212 | */ | ||
1213 | void usb_autopm_put_interface(struct usb_interface *intf) | ||
1214 | { | ||
1215 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1216 | |||
1217 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
1218 | if (intf->condition != USB_INTERFACE_UNBOUND) { | ||
1219 | if (--intf->pm_usage_cnt <= 0) | ||
1220 | schedule_delayed_work(&udev->autosuspend, | ||
1221 | USB_AUTOSUSPEND_DELAY); | ||
1222 | } | ||
1223 | mutex_unlock(&udev->pm_mutex); | ||
1224 | // dev_dbg(&intf->dev, "%s: cnt %d\n", | ||
1225 | // __FUNCTION__, intf->pm_usage_cnt); | ||
1226 | } | ||
1227 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface); | ||
1228 | |||
1229 | /** | ||
1230 | * usb_autopm_get_interface - increment a USB interface's PM-usage counter | ||
1231 | * @intf - the usb_interface whose counter should be incremented | ||
1232 | * | ||
1233 | * This routine should be called by an interface driver when it wants to | ||
1234 | * use @intf and needs to guarantee that it is not suspended. In addition, | ||
1235 | * the routine prevents @intf from being autosuspended subsequently. (Note | ||
1236 | * that this will not prevent suspend events originating in the PM core.) | ||
1237 | * This prevention will persist until usb_autopm_put_interface() is called | ||
1238 | * or @intf is unbound. A typical example would be a character-device | ||
1239 | * driver when its device file is opened. | ||
1240 | * | ||
1241 | * The routine increments @intf's usage counter. So long as the counter | ||
1242 | * is greater than 0, autosuspend will not be allowed for @intf or its | ||
1243 | * usb_device. When the driver is finished using @intf it should call | ||
1244 | * usb_autopm_put_interface() to decrement the usage counter and queue | ||
1245 | * a delayed autosuspend request (if the counter is <= 0). | ||
1246 | * | ||
1247 | * Note that @intf->pm_usage_cnt is owned by the interface driver. The | ||
1248 | * core will not change its value other than the increment and decrement | ||
1249 | * in usb_autopm_get_interface and usb_autopm_put_interface. The driver | ||
1250 | * may use this simple counter-oriented discipline or may set the value | ||
1251 | * any way it likes. | ||
1252 | * | ||
1253 | * Resume method calls generated by this routine can arrive at any time | ||
1254 | * while @intf is suspended. They are not protected by the usb_device's | ||
1255 | * lock but only by its pm_mutex. Drivers must provide their own | ||
1256 | * synchronization. | ||
1257 | * | ||
1258 | * This routine can run only in process context. | ||
1259 | */ | ||
1260 | int usb_autopm_get_interface(struct usb_interface *intf) | ||
1261 | { | ||
1262 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1263 | int status; | ||
1264 | |||
1265 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
1266 | if (intf->condition == USB_INTERFACE_UNBOUND) | ||
1267 | status = -ENODEV; | ||
1268 | else { | ||
1269 | ++intf->pm_usage_cnt; | ||
1270 | udev->auto_pm = 1; | ||
1271 | status = usb_resume_both(udev); | ||
1272 | if (status != 0) | ||
1273 | --intf->pm_usage_cnt; | ||
1274 | } | ||
1275 | mutex_unlock(&udev->pm_mutex); | ||
1276 | // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", | ||
1277 | // __FUNCTION__, status, intf->pm_usage_cnt); | ||
1278 | return status; | ||
1279 | } | ||
1280 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface); | ||
1281 | |||
1282 | #endif /* CONFIG_USB_SUSPEND */ | ||
1283 | |||
1284 | static int usb_suspend(struct device *dev, pm_message_t message) | ||
1285 | { | ||
1286 | int status; | ||
1287 | |||
1288 | if (is_usb_device(dev)) { | ||
1289 | struct usb_device *udev = to_usb_device(dev); | ||
1290 | |||
1291 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
1292 | udev->auto_pm = 0; | ||
1293 | status = usb_suspend_both(udev, message); | ||
1294 | mutex_unlock(&udev->pm_mutex); | ||
1295 | } else | ||
1296 | status = 0; | ||
1297 | return status; | ||
1298 | } | ||
1299 | |||
1300 | static int usb_resume(struct device *dev) | ||
1301 | { | ||
1302 | int status; | ||
1303 | |||
1304 | if (is_usb_device(dev)) { | ||
1305 | struct usb_device *udev = to_usb_device(dev); | ||
1306 | |||
1307 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
1308 | udev->auto_pm = 0; | ||
1309 | status = usb_resume_both(udev); | ||
1310 | mutex_unlock(&udev->pm_mutex); | ||
1311 | |||
1312 | /* Rebind drivers that had no suspend method? */ | ||
1313 | } else | ||
1314 | status = 0; | ||
1315 | return status; | ||
1316 | } | ||
1317 | |||
1318 | #endif /* CONFIG_PM */ | ||
1319 | |||
1320 | struct bus_type usb_bus_type = { | ||
1321 | .name = "usb", | ||
1322 | .match = usb_device_match, | ||
1323 | .uevent = usb_uevent, | ||
1324 | #ifdef CONFIG_PM | ||
1325 | .suspend = usb_suspend, | ||
1326 | .resume = usb_resume, | ||
1327 | #endif | ||
1328 | }; | ||
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 247b5a4913a8..3ebb90149e93 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c | |||
@@ -207,9 +207,9 @@ static void ep_device_release(struct device *dev) | |||
207 | kfree(ep_dev); | 207 | kfree(ep_dev); |
208 | } | 208 | } |
209 | 209 | ||
210 | void usb_create_ep_files(struct device *parent, | 210 | int usb_create_ep_files(struct device *parent, |
211 | struct usb_host_endpoint *endpoint, | 211 | struct usb_host_endpoint *endpoint, |
212 | struct usb_device *udev) | 212 | struct usb_device *udev) |
213 | { | 213 | { |
214 | char name[8]; | 214 | char name[8]; |
215 | struct ep_device *ep_dev; | 215 | struct ep_device *ep_dev; |
@@ -242,19 +242,33 @@ void usb_create_ep_files(struct device *parent, | |||
242 | retval = device_register(&ep_dev->dev); | 242 | retval = device_register(&ep_dev->dev); |
243 | if (retval) | 243 | if (retval) |
244 | goto error; | 244 | goto error; |
245 | sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); | 245 | retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); |
246 | if (retval) | ||
247 | goto error_group; | ||
246 | 248 | ||
247 | endpoint->ep_dev = ep_dev; | 249 | endpoint->ep_dev = ep_dev; |
248 | 250 | ||
249 | /* create the symlink to the old-style "ep_XX" directory */ | 251 | /* create the symlink to the old-style "ep_XX" directory */ |
250 | sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); | 252 | sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); |
251 | sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name); | 253 | retval = sysfs_create_link(&parent->kobj, |
252 | 254 | &endpoint->ep_dev->dev.kobj, name); | |
255 | if (retval) | ||
256 | goto error_link; | ||
253 | exit: | 257 | exit: |
254 | return; | 258 | return retval; |
259 | |||
260 | error_link: | ||
261 | sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); | ||
262 | |||
263 | error_group: | ||
264 | device_unregister(&ep_dev->dev); | ||
265 | endpoint->ep_dev = NULL; | ||
266 | destroy_endpoint_class(); | ||
267 | return retval; | ||
255 | error: | 268 | error: |
256 | kfree(ep_dev); | 269 | kfree(ep_dev); |
257 | return; | 270 | destroy_endpoint_class(); |
271 | return retval; | ||
258 | } | 272 | } |
259 | 273 | ||
260 | void usb_remove_ep_files(struct usb_host_endpoint *endpoint) | 274 | void usb_remove_ep_files(struct usb_host_endpoint *endpoint) |
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 8de4f8c99d61..c376c655c5de 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
@@ -55,7 +55,7 @@ static int usb_open(struct inode * inode, struct file * file) | |||
55 | return err; | 55 | return err; |
56 | } | 56 | } |
57 | 57 | ||
58 | static struct file_operations usb_fops = { | 58 | static const struct file_operations usb_fops = { |
59 | .owner = THIS_MODULE, | 59 | .owner = THIS_MODULE, |
60 | .open = usb_open, | 60 | .open = usb_open, |
61 | }; | 61 | }; |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c new file mode 100644 index 000000000000..16332cc57946 --- /dev/null +++ b/drivers/usb/core/generic.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * drivers/usb/generic.c - generic driver for USB devices (not interfaces) | ||
3 | * | ||
4 | * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de> | ||
5 | * | ||
6 | * based on drivers/usb/usb.c which had the following copyrights: | ||
7 | * (C) Copyright Linus Torvalds 1999 | ||
8 | * (C) Copyright Johannes Erdfelt 1999-2001 | ||
9 | * (C) Copyright Andreas Gal 1999 | ||
10 | * (C) Copyright Gregory P. Smith 1999 | ||
11 | * (C) Copyright Deti Fliegl 1999 (new USB architecture) | ||
12 | * (C) Copyright Randy Dunlap 2000 | ||
13 | * (C) Copyright David Brownell 2000-2004 | ||
14 | * (C) Copyright Yggdrasil Computing, Inc. 2000 | ||
15 | * (usb_device_id matching changes by Adam J. Richter) | ||
16 | * (C) Copyright Greg Kroah-Hartman 2002-2003 | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include "usb.h" | ||
23 | |||
24 | static inline const char *plural(int n) | ||
25 | { | ||
26 | return (n == 1 ? "" : "s"); | ||
27 | } | ||
28 | |||
29 | static int choose_configuration(struct usb_device *udev) | ||
30 | { | ||
31 | int i; | ||
32 | int num_configs; | ||
33 | int insufficient_power = 0; | ||
34 | struct usb_host_config *c, *best; | ||
35 | |||
36 | best = NULL; | ||
37 | c = udev->config; | ||
38 | num_configs = udev->descriptor.bNumConfigurations; | ||
39 | for (i = 0; i < num_configs; (i++, c++)) { | ||
40 | struct usb_interface_descriptor *desc = NULL; | ||
41 | |||
42 | /* It's possible that a config has no interfaces! */ | ||
43 | if (c->desc.bNumInterfaces > 0) | ||
44 | desc = &c->intf_cache[0]->altsetting->desc; | ||
45 | |||
46 | /* | ||
47 | * HP's USB bus-powered keyboard has only one configuration | ||
48 | * and it claims to be self-powered; other devices may have | ||
49 | * similar errors in their descriptors. If the next test | ||
50 | * were allowed to execute, such configurations would always | ||
51 | * be rejected and the devices would not work as expected. | ||
52 | * In the meantime, we run the risk of selecting a config | ||
53 | * that requires external power at a time when that power | ||
54 | * isn't available. It seems to be the lesser of two evils. | ||
55 | * | ||
56 | * Bugzilla #6448 reports a device that appears to crash | ||
57 | * when it receives a GET_DEVICE_STATUS request! We don't | ||
58 | * have any other way to tell whether a device is self-powered, | ||
59 | * but since we don't use that information anywhere but here, | ||
60 | * the call has been removed. | ||
61 | * | ||
62 | * Maybe the GET_DEVICE_STATUS call and the test below can | ||
63 | * be reinstated when device firmwares become more reliable. | ||
64 | * Don't hold your breath. | ||
65 | */ | ||
66 | #if 0 | ||
67 | /* Rule out self-powered configs for a bus-powered device */ | ||
68 | if (bus_powered && (c->desc.bmAttributes & | ||
69 | USB_CONFIG_ATT_SELFPOWER)) | ||
70 | continue; | ||
71 | #endif | ||
72 | |||
73 | /* | ||
74 | * The next test may not be as effective as it should be. | ||
75 | * Some hubs have errors in their descriptor, claiming | ||
76 | * to be self-powered when they are really bus-powered. | ||
77 | * We will overestimate the amount of current such hubs | ||
78 | * make available for each port. | ||
79 | * | ||
80 | * This is a fairly benign sort of failure. It won't | ||
81 | * cause us to reject configurations that we should have | ||
82 | * accepted. | ||
83 | */ | ||
84 | |||
85 | /* Rule out configs that draw too much bus current */ | ||
86 | if (c->desc.bMaxPower * 2 > udev->bus_mA) { | ||
87 | insufficient_power++; | ||
88 | continue; | ||
89 | } | ||
90 | |||
91 | /* If the first config's first interface is COMM/2/0xff | ||
92 | * (MSFT RNDIS), rule it out unless Linux has host-side | ||
93 | * RNDIS support. */ | ||
94 | if (i == 0 && desc | ||
95 | && desc->bInterfaceClass == USB_CLASS_COMM | ||
96 | && desc->bInterfaceSubClass == 2 | ||
97 | && desc->bInterfaceProtocol == 0xff) { | ||
98 | #ifndef CONFIG_USB_NET_RNDIS_HOST | ||
99 | continue; | ||
100 | #else | ||
101 | best = c; | ||
102 | #endif | ||
103 | } | ||
104 | |||
105 | /* From the remaining configs, choose the first one whose | ||
106 | * first interface is for a non-vendor-specific class. | ||
107 | * Reason: Linux is more likely to have a class driver | ||
108 | * than a vendor-specific driver. */ | ||
109 | else if (udev->descriptor.bDeviceClass != | ||
110 | USB_CLASS_VENDOR_SPEC && | ||
111 | (!desc || desc->bInterfaceClass != | ||
112 | USB_CLASS_VENDOR_SPEC)) { | ||
113 | best = c; | ||
114 | break; | ||
115 | } | ||
116 | |||
117 | /* If all the remaining configs are vendor-specific, | ||
118 | * choose the first one. */ | ||
119 | else if (!best) | ||
120 | best = c; | ||
121 | } | ||
122 | |||
123 | if (insufficient_power > 0) | ||
124 | dev_info(&udev->dev, "rejected %d configuration%s " | ||
125 | "due to insufficient available bus power\n", | ||
126 | insufficient_power, plural(insufficient_power)); | ||
127 | |||
128 | if (best) { | ||
129 | i = best->desc.bConfigurationValue; | ||
130 | dev_info(&udev->dev, | ||
131 | "configuration #%d chosen from %d choice%s\n", | ||
132 | i, num_configs, plural(num_configs)); | ||
133 | } else { | ||
134 | i = -1; | ||
135 | dev_warn(&udev->dev, | ||
136 | "no configuration chosen from %d choice%s\n", | ||
137 | num_configs, plural(num_configs)); | ||
138 | } | ||
139 | return i; | ||
140 | } | ||
141 | |||
142 | static int generic_probe(struct usb_device *udev) | ||
143 | { | ||
144 | int err, c; | ||
145 | |||
146 | /* put device-specific files into sysfs */ | ||
147 | usb_create_sysfs_dev_files(udev); | ||
148 | |||
149 | /* Choose and set the configuration. This registers the interfaces | ||
150 | * with the driver core and lets interface drivers bind to them. | ||
151 | */ | ||
152 | c = choose_configuration(udev); | ||
153 | if (c >= 0) { | ||
154 | err = usb_set_configuration(udev, c); | ||
155 | if (err) { | ||
156 | dev_err(&udev->dev, "can't set config #%d, error %d\n", | ||
157 | c, err); | ||
158 | /* This need not be fatal. The user can try to | ||
159 | * set other configurations. */ | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* USB device state == configured ... usable */ | ||
164 | usb_notify_add_device(udev); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static void generic_disconnect(struct usb_device *udev) | ||
170 | { | ||
171 | usb_notify_remove_device(udev); | ||
172 | |||
173 | /* if this is only an unbind, not a physical disconnect, then | ||
174 | * unconfigure the device */ | ||
175 | if (udev->actconfig) | ||
176 | usb_set_configuration(udev, 0); | ||
177 | |||
178 | usb_remove_sysfs_dev_files(udev); | ||
179 | } | ||
180 | |||
181 | #ifdef CONFIG_PM | ||
182 | |||
183 | static int generic_suspend(struct usb_device *udev, pm_message_t msg) | ||
184 | { | ||
185 | /* USB devices enter SUSPEND state through their hubs, but can be | ||
186 | * marked for FREEZE as soon as their children are already idled. | ||
187 | * But those semantics are useless, so we equate the two (sigh). | ||
188 | */ | ||
189 | return usb_port_suspend(udev); | ||
190 | } | ||
191 | |||
192 | static int generic_resume(struct usb_device *udev) | ||
193 | { | ||
194 | return usb_port_resume(udev); | ||
195 | } | ||
196 | |||
197 | #endif /* CONFIG_PM */ | ||
198 | |||
199 | struct usb_device_driver usb_generic_driver = { | ||
200 | .name = "usb", | ||
201 | .probe = generic_probe, | ||
202 | .disconnect = generic_disconnect, | ||
203 | #ifdef CONFIG_PM | ||
204 | .suspend = generic_suspend, | ||
205 | .resume = generic_resume, | ||
206 | #endif | ||
207 | .supports_autosuspend = 1, | ||
208 | }; | ||
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 5078fb3375e3..edf4300a3f7a 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -281,7 +281,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) | |||
281 | (void) usb_hcd_pci_resume (dev); | 281 | (void) usb_hcd_pci_resume (dev); |
282 | } | 282 | } |
283 | 283 | ||
284 | } else { | 284 | } else if (hcd->state != HC_STATE_HALT) { |
285 | dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n", | 285 | dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n", |
286 | hcd->state); | 286 | hcd->state); |
287 | WARN_ON(1); | 287 | WARN_ON(1); |
@@ -413,4 +413,20 @@ EXPORT_SYMBOL (usb_hcd_pci_resume); | |||
413 | 413 | ||
414 | #endif /* CONFIG_PM */ | 414 | #endif /* CONFIG_PM */ |
415 | 415 | ||
416 | /** | ||
417 | * usb_hcd_pci_shutdown - shutdown host controller | ||
418 | * @dev: USB Host Controller being shutdown | ||
419 | */ | ||
420 | void usb_hcd_pci_shutdown (struct pci_dev *dev) | ||
421 | { | ||
422 | struct usb_hcd *hcd; | ||
423 | |||
424 | hcd = pci_get_drvdata(dev); | ||
425 | if (!hcd) | ||
426 | return; | ||
427 | |||
428 | if (hcd->driver->shutdown) | ||
429 | hcd->driver->shutdown(hcd); | ||
430 | } | ||
431 | EXPORT_SYMBOL (usb_hcd_pci_shutdown); | ||
416 | 432 | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fb4d058bbde0..e86f62957085 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/byteorder.h> | 38 | #include <asm/byteorder.h> |
39 | #include <linux/platform_device.h> | ||
39 | 40 | ||
40 | #include <linux/usb.h> | 41 | #include <linux/usb.h> |
41 | 42 | ||
@@ -632,31 +633,20 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) | |||
632 | 633 | ||
633 | /*-------------------------------------------------------------------------*/ | 634 | /*-------------------------------------------------------------------------*/ |
634 | 635 | ||
635 | /* Asynchronous unlinks of root-hub control URBs are legal, but they | 636 | /* Unlinks of root-hub control URBs are legal, but they don't do anything |
636 | * don't do anything. Status URB unlinks must be made in process context | 637 | * since these URBs always execute synchronously. |
637 | * with interrupts enabled. | ||
638 | */ | 638 | */ |
639 | static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 639 | static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) |
640 | { | 640 | { |
641 | if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */ | 641 | unsigned long flags; |
642 | if (in_interrupt()) | ||
643 | return 0; /* nothing to do */ | ||
644 | |||
645 | spin_lock_irq(&urb->lock); /* from usb_kill_urb */ | ||
646 | ++urb->reject; | ||
647 | spin_unlock_irq(&urb->lock); | ||
648 | |||
649 | wait_event(usb_kill_urb_queue, | ||
650 | atomic_read(&urb->use_count) == 0); | ||
651 | 642 | ||
652 | spin_lock_irq(&urb->lock); | 643 | if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */ |
653 | --urb->reject; | 644 | ; /* Do nothing */ |
654 | spin_unlock_irq(&urb->lock); | ||
655 | 645 | ||
656 | } else { /* Status URB */ | 646 | } else { /* Status URB */ |
657 | if (!hcd->uses_new_polling) | 647 | if (!hcd->uses_new_polling) |
658 | del_timer_sync (&hcd->rh_timer); | 648 | del_timer (&hcd->rh_timer); |
659 | local_irq_disable (); | 649 | local_irq_save (flags); |
660 | spin_lock (&hcd_root_hub_lock); | 650 | spin_lock (&hcd_root_hub_lock); |
661 | if (urb == hcd->status_urb) { | 651 | if (urb == hcd->status_urb) { |
662 | hcd->status_urb = NULL; | 652 | hcd->status_urb = NULL; |
@@ -666,7 +656,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
666 | spin_unlock (&hcd_root_hub_lock); | 656 | spin_unlock (&hcd_root_hub_lock); |
667 | if (urb) | 657 | if (urb) |
668 | usb_hcd_giveback_urb (hcd, urb, NULL); | 658 | usb_hcd_giveback_urb (hcd, urb, NULL); |
669 | local_irq_enable (); | 659 | local_irq_restore (flags); |
670 | } | 660 | } |
671 | 661 | ||
672 | return 0; | 662 | return 0; |
@@ -674,31 +664,6 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
674 | 664 | ||
675 | /*-------------------------------------------------------------------------*/ | 665 | /*-------------------------------------------------------------------------*/ |
676 | 666 | ||
677 | /* exported only within usbcore */ | ||
678 | struct usb_bus *usb_bus_get(struct usb_bus *bus) | ||
679 | { | ||
680 | if (bus) | ||
681 | kref_get(&bus->kref); | ||
682 | return bus; | ||
683 | } | ||
684 | |||
685 | static void usb_host_release(struct kref *kref) | ||
686 | { | ||
687 | struct usb_bus *bus = container_of(kref, struct usb_bus, kref); | ||
688 | |||
689 | if (bus->release) | ||
690 | bus->release(bus); | ||
691 | } | ||
692 | |||
693 | /* exported only within usbcore */ | ||
694 | void usb_bus_put(struct usb_bus *bus) | ||
695 | { | ||
696 | if (bus) | ||
697 | kref_put(&bus->kref, usb_host_release); | ||
698 | } | ||
699 | |||
700 | /*-------------------------------------------------------------------------*/ | ||
701 | |||
702 | static struct class *usb_host_class; | 667 | static struct class *usb_host_class; |
703 | 668 | ||
704 | int usb_host_init(void) | 669 | int usb_host_init(void) |
@@ -730,39 +695,12 @@ static void usb_bus_init (struct usb_bus *bus) | |||
730 | bus->devnum_next = 1; | 695 | bus->devnum_next = 1; |
731 | 696 | ||
732 | bus->root_hub = NULL; | 697 | bus->root_hub = NULL; |
733 | bus->hcpriv = NULL; | ||
734 | bus->busnum = -1; | 698 | bus->busnum = -1; |
735 | bus->bandwidth_allocated = 0; | 699 | bus->bandwidth_allocated = 0; |
736 | bus->bandwidth_int_reqs = 0; | 700 | bus->bandwidth_int_reqs = 0; |
737 | bus->bandwidth_isoc_reqs = 0; | 701 | bus->bandwidth_isoc_reqs = 0; |
738 | 702 | ||
739 | INIT_LIST_HEAD (&bus->bus_list); | 703 | INIT_LIST_HEAD (&bus->bus_list); |
740 | |||
741 | kref_init(&bus->kref); | ||
742 | } | ||
743 | |||
744 | /** | ||
745 | * usb_alloc_bus - creates a new USB host controller structure | ||
746 | * @op: pointer to a struct usb_operations that this bus structure should use | ||
747 | * Context: !in_interrupt() | ||
748 | * | ||
749 | * Creates a USB host controller bus structure with the specified | ||
750 | * usb_operations and initializes all the necessary internal objects. | ||
751 | * | ||
752 | * If no memory is available, NULL is returned. | ||
753 | * | ||
754 | * The caller should call usb_put_bus() when it is finished with the structure. | ||
755 | */ | ||
756 | struct usb_bus *usb_alloc_bus (struct usb_operations *op) | ||
757 | { | ||
758 | struct usb_bus *bus; | ||
759 | |||
760 | bus = kzalloc (sizeof *bus, GFP_KERNEL); | ||
761 | if (!bus) | ||
762 | return NULL; | ||
763 | usb_bus_init (bus); | ||
764 | bus->op = op; | ||
765 | return bus; | ||
766 | } | 704 | } |
767 | 705 | ||
768 | /*-------------------------------------------------------------------------*/ | 706 | /*-------------------------------------------------------------------------*/ |
@@ -1112,10 +1050,10 @@ static void urb_unlink (struct urb *urb) | |||
1112 | * expects usb_submit_urb() to have sanity checked and conditioned all | 1050 | * expects usb_submit_urb() to have sanity checked and conditioned all |
1113 | * inputs in the urb | 1051 | * inputs in the urb |
1114 | */ | 1052 | */ |
1115 | static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | 1053 | int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) |
1116 | { | 1054 | { |
1117 | int status; | 1055 | int status; |
1118 | struct usb_hcd *hcd = urb->dev->bus->hcpriv; | 1056 | struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); |
1119 | struct usb_host_endpoint *ep; | 1057 | struct usb_host_endpoint *ep; |
1120 | unsigned long flags; | 1058 | unsigned long flags; |
1121 | 1059 | ||
@@ -1186,7 +1124,7 @@ doit: | |||
1186 | /* lower level hcd code should use *_dma exclusively, | 1124 | /* lower level hcd code should use *_dma exclusively, |
1187 | * unless it uses pio or talks to another transport. | 1125 | * unless it uses pio or talks to another transport. |
1188 | */ | 1126 | */ |
1189 | if (hcd->self.controller->dma_mask) { | 1127 | if (hcd->self.uses_dma) { |
1190 | if (usb_pipecontrol (urb->pipe) | 1128 | if (usb_pipecontrol (urb->pipe) |
1191 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | 1129 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) |
1192 | urb->setup_dma = dma_map_single ( | 1130 | urb->setup_dma = dma_map_single ( |
@@ -1221,9 +1159,10 @@ done: | |||
1221 | /*-------------------------------------------------------------------------*/ | 1159 | /*-------------------------------------------------------------------------*/ |
1222 | 1160 | ||
1223 | /* called in any context */ | 1161 | /* called in any context */ |
1224 | static int hcd_get_frame_number (struct usb_device *udev) | 1162 | int usb_hcd_get_frame_number (struct usb_device *udev) |
1225 | { | 1163 | { |
1226 | struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv; | 1164 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); |
1165 | |||
1227 | if (!HC_IS_RUNNING (hcd->state)) | 1166 | if (!HC_IS_RUNNING (hcd->state)) |
1228 | return -ESHUTDOWN; | 1167 | return -ESHUTDOWN; |
1229 | return hcd->driver->get_frame_number (hcd); | 1168 | return hcd->driver->get_frame_number (hcd); |
@@ -1263,7 +1202,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb) | |||
1263 | * caller guarantees urb won't be recycled till both unlink() | 1202 | * caller guarantees urb won't be recycled till both unlink() |
1264 | * and the urb's completion function return | 1203 | * and the urb's completion function return |
1265 | */ | 1204 | */ |
1266 | static int hcd_unlink_urb (struct urb *urb, int status) | 1205 | int usb_hcd_unlink_urb (struct urb *urb, int status) |
1267 | { | 1206 | { |
1268 | struct usb_host_endpoint *ep; | 1207 | struct usb_host_endpoint *ep; |
1269 | struct usb_hcd *hcd = NULL; | 1208 | struct usb_hcd *hcd = NULL; |
@@ -1296,7 +1235,7 @@ static int hcd_unlink_urb (struct urb *urb, int status) | |||
1296 | spin_lock (&hcd_data_lock); | 1235 | spin_lock (&hcd_data_lock); |
1297 | 1236 | ||
1298 | sys = &urb->dev->dev; | 1237 | sys = &urb->dev->dev; |
1299 | hcd = urb->dev->bus->hcpriv; | 1238 | hcd = bus_to_hcd(urb->dev->bus); |
1300 | if (hcd == NULL) { | 1239 | if (hcd == NULL) { |
1301 | retval = -ENODEV; | 1240 | retval = -ENODEV; |
1302 | goto done; | 1241 | goto done; |
@@ -1354,41 +1293,33 @@ done: | |||
1354 | /*-------------------------------------------------------------------------*/ | 1293 | /*-------------------------------------------------------------------------*/ |
1355 | 1294 | ||
1356 | /* disables the endpoint: cancels any pending urbs, then synchronizes with | 1295 | /* disables the endpoint: cancels any pending urbs, then synchronizes with |
1357 | * the hcd to make sure all endpoint state is gone from hardware. use for | 1296 | * the hcd to make sure all endpoint state is gone from hardware, and then |
1297 | * waits until the endpoint's queue is completely drained. use for | ||
1358 | * set_configuration, set_interface, driver removal, physical disconnect. | 1298 | * set_configuration, set_interface, driver removal, physical disconnect. |
1359 | * | 1299 | * |
1360 | * example: a qh stored in ep->hcpriv, holding state related to endpoint | 1300 | * example: a qh stored in ep->hcpriv, holding state related to endpoint |
1361 | * type, maxpacket size, toggle, halt status, and scheduling. | 1301 | * type, maxpacket size, toggle, halt status, and scheduling. |
1362 | */ | 1302 | */ |
1363 | static void | 1303 | void usb_hcd_endpoint_disable (struct usb_device *udev, |
1364 | hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep) | 1304 | struct usb_host_endpoint *ep) |
1365 | { | 1305 | { |
1366 | struct usb_hcd *hcd; | 1306 | struct usb_hcd *hcd; |
1367 | struct urb *urb; | 1307 | struct urb *urb; |
1368 | 1308 | ||
1369 | hcd = udev->bus->hcpriv; | 1309 | hcd = bus_to_hcd(udev->bus); |
1370 | 1310 | ||
1371 | WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT && | 1311 | WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT && |
1372 | udev->state != USB_STATE_NOTATTACHED); | 1312 | udev->state != USB_STATE_NOTATTACHED); |
1373 | 1313 | ||
1374 | local_irq_disable (); | 1314 | local_irq_disable (); |
1375 | 1315 | ||
1376 | /* FIXME move most of this into message.c as part of its | ||
1377 | * endpoint disable logic | ||
1378 | */ | ||
1379 | |||
1380 | /* ep is already gone from udev->ep_{in,out}[]; no more submits */ | 1316 | /* ep is already gone from udev->ep_{in,out}[]; no more submits */ |
1381 | rescan: | 1317 | rescan: |
1382 | spin_lock (&hcd_data_lock); | 1318 | spin_lock (&hcd_data_lock); |
1383 | list_for_each_entry (urb, &ep->urb_list, urb_list) { | 1319 | list_for_each_entry (urb, &ep->urb_list, urb_list) { |
1384 | int tmp; | 1320 | int tmp; |
1385 | 1321 | ||
1386 | /* another cpu may be in hcd, spinning on hcd_data_lock | 1322 | /* the urb may already have been unlinked */ |
1387 | * to giveback() this urb. the races here should be | ||
1388 | * small, but a full fix needs a new "can't submit" | ||
1389 | * urb state. | ||
1390 | * FIXME urb->reject should allow that... | ||
1391 | */ | ||
1392 | if (urb->status != -EINPROGRESS) | 1323 | if (urb->status != -EINPROGRESS) |
1393 | continue; | 1324 | continue; |
1394 | usb_get_urb (urb); | 1325 | usb_get_urb (urb); |
@@ -1430,6 +1361,30 @@ rescan: | |||
1430 | might_sleep (); | 1361 | might_sleep (); |
1431 | if (hcd->driver->endpoint_disable) | 1362 | if (hcd->driver->endpoint_disable) |
1432 | hcd->driver->endpoint_disable (hcd, ep); | 1363 | hcd->driver->endpoint_disable (hcd, ep); |
1364 | |||
1365 | /* Wait until the endpoint queue is completely empty. Most HCDs | ||
1366 | * will have done this already in their endpoint_disable method, | ||
1367 | * but some might not. And there could be root-hub control URBs | ||
1368 | * still pending since they aren't affected by the HCDs' | ||
1369 | * endpoint_disable methods. | ||
1370 | */ | ||
1371 | while (!list_empty (&ep->urb_list)) { | ||
1372 | spin_lock_irq (&hcd_data_lock); | ||
1373 | |||
1374 | /* The list may have changed while we acquired the spinlock */ | ||
1375 | urb = NULL; | ||
1376 | if (!list_empty (&ep->urb_list)) { | ||
1377 | urb = list_entry (ep->urb_list.prev, struct urb, | ||
1378 | urb_list); | ||
1379 | usb_get_urb (urb); | ||
1380 | } | ||
1381 | spin_unlock_irq (&hcd_data_lock); | ||
1382 | |||
1383 | if (urb) { | ||
1384 | usb_kill_urb (urb); | ||
1385 | usb_put_urb (urb); | ||
1386 | } | ||
1387 | } | ||
1433 | } | 1388 | } |
1434 | 1389 | ||
1435 | /*-------------------------------------------------------------------------*/ | 1390 | /*-------------------------------------------------------------------------*/ |
@@ -1476,50 +1431,6 @@ int hcd_bus_resume (struct usb_bus *bus) | |||
1476 | return status; | 1431 | return status; |
1477 | } | 1432 | } |
1478 | 1433 | ||
1479 | /* | ||
1480 | * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports | ||
1481 | * @hcd: host controller for this root hub | ||
1482 | * | ||
1483 | * This call arranges that usb_hcd_resume_root_hub() is safe to call later; | ||
1484 | * that the HCD's root hub polling is deactivated; and that the root's hub | ||
1485 | * driver is suspended. HCDs may call this to autosuspend when their root | ||
1486 | * hub's downstream ports are all inactive: unpowered, disconnected, | ||
1487 | * disabled, or suspended. | ||
1488 | * | ||
1489 | * The HCD will autoresume on device connect change detection (using SRP | ||
1490 | * or a D+/D- pullup). The HCD also autoresumes on remote wakeup signaling | ||
1491 | * from any ports that are suspended (if that is enabled). In most cases, | ||
1492 | * overcurrent signaling (on powered ports) will also start autoresume. | ||
1493 | * | ||
1494 | * Always called with IRQs blocked. | ||
1495 | */ | ||
1496 | void usb_hcd_suspend_root_hub (struct usb_hcd *hcd) | ||
1497 | { | ||
1498 | struct urb *urb; | ||
1499 | |||
1500 | spin_lock (&hcd_root_hub_lock); | ||
1501 | usb_suspend_root_hub (hcd->self.root_hub); | ||
1502 | |||
1503 | /* force status urb to complete/unlink while suspended */ | ||
1504 | if (hcd->status_urb) { | ||
1505 | urb = hcd->status_urb; | ||
1506 | urb->status = -ECONNRESET; | ||
1507 | urb->hcpriv = NULL; | ||
1508 | urb->actual_length = 0; | ||
1509 | |||
1510 | del_timer (&hcd->rh_timer); | ||
1511 | hcd->poll_pending = 0; | ||
1512 | hcd->status_urb = NULL; | ||
1513 | } else | ||
1514 | urb = NULL; | ||
1515 | spin_unlock (&hcd_root_hub_lock); | ||
1516 | hcd->state = HC_STATE_SUSPENDED; | ||
1517 | |||
1518 | if (urb) | ||
1519 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
1520 | } | ||
1521 | EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub); | ||
1522 | |||
1523 | /** | 1434 | /** |
1524 | * usb_hcd_resume_root_hub - called by HCD to resume its root hub | 1435 | * usb_hcd_resume_root_hub - called by HCD to resume its root hub |
1525 | * @hcd: host controller for this root hub | 1436 | * @hcd: host controller for this root hub |
@@ -1583,20 +1494,6 @@ EXPORT_SYMBOL (usb_bus_start_enum); | |||
1583 | 1494 | ||
1584 | /*-------------------------------------------------------------------------*/ | 1495 | /*-------------------------------------------------------------------------*/ |
1585 | 1496 | ||
1586 | /* | ||
1587 | * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue) | ||
1588 | */ | ||
1589 | static struct usb_operations usb_hcd_operations = { | ||
1590 | .get_frame_number = hcd_get_frame_number, | ||
1591 | .submit_urb = hcd_submit_urb, | ||
1592 | .unlink_urb = hcd_unlink_urb, | ||
1593 | .buffer_alloc = hcd_buffer_alloc, | ||
1594 | .buffer_free = hcd_buffer_free, | ||
1595 | .disable = hcd_endpoint_disable, | ||
1596 | }; | ||
1597 | |||
1598 | /*-------------------------------------------------------------------------*/ | ||
1599 | |||
1600 | /** | 1497 | /** |
1601 | * usb_hcd_giveback_urb - return URB from HCD to device driver | 1498 | * usb_hcd_giveback_urb - return URB from HCD to device driver |
1602 | * @hcd: host controller returning the URB | 1499 | * @hcd: host controller returning the URB |
@@ -1617,8 +1514,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs | |||
1617 | at_root_hub = (urb->dev == hcd->self.root_hub); | 1514 | at_root_hub = (urb->dev == hcd->self.root_hub); |
1618 | urb_unlink (urb); | 1515 | urb_unlink (urb); |
1619 | 1516 | ||
1620 | /* lower level hcd code should use *_dma exclusively */ | 1517 | /* lower level hcd code should use *_dma exclusively if the |
1621 | if (hcd->self.controller->dma_mask && !at_root_hub) { | 1518 | * host controller does DMA */ |
1519 | if (hcd->self.uses_dma && !at_root_hub) { | ||
1622 | if (usb_pipecontrol (urb->pipe) | 1520 | if (usb_pipecontrol (urb->pipe) |
1623 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | 1521 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) |
1624 | dma_unmap_single (hcd->self.controller, urb->setup_dma, | 1522 | dma_unmap_single (hcd->self.controller, urb->setup_dma, |
@@ -1704,14 +1602,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died); | |||
1704 | 1602 | ||
1705 | /*-------------------------------------------------------------------------*/ | 1603 | /*-------------------------------------------------------------------------*/ |
1706 | 1604 | ||
1707 | static void hcd_release (struct usb_bus *bus) | ||
1708 | { | ||
1709 | struct usb_hcd *hcd; | ||
1710 | |||
1711 | hcd = container_of(bus, struct usb_hcd, self); | ||
1712 | kfree(hcd); | ||
1713 | } | ||
1714 | |||
1715 | /** | 1605 | /** |
1716 | * usb_create_hcd - create and initialize an HCD structure | 1606 | * usb_create_hcd - create and initialize an HCD structure |
1717 | * @driver: HC driver that will use this hcd | 1607 | * @driver: HC driver that will use this hcd |
@@ -1736,13 +1626,12 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | |||
1736 | return NULL; | 1626 | return NULL; |
1737 | } | 1627 | } |
1738 | dev_set_drvdata(dev, hcd); | 1628 | dev_set_drvdata(dev, hcd); |
1629 | kref_init(&hcd->kref); | ||
1739 | 1630 | ||
1740 | usb_bus_init(&hcd->self); | 1631 | usb_bus_init(&hcd->self); |
1741 | hcd->self.op = &usb_hcd_operations; | ||
1742 | hcd->self.hcpriv = hcd; | ||
1743 | hcd->self.release = &hcd_release; | ||
1744 | hcd->self.controller = dev; | 1632 | hcd->self.controller = dev; |
1745 | hcd->self.bus_name = bus_name; | 1633 | hcd->self.bus_name = bus_name; |
1634 | hcd->self.uses_dma = (dev->dma_mask != NULL); | ||
1746 | 1635 | ||
1747 | init_timer(&hcd->rh_timer); | 1636 | init_timer(&hcd->rh_timer); |
1748 | hcd->rh_timer.function = rh_timer_func; | 1637 | hcd->rh_timer.function = rh_timer_func; |
@@ -1756,10 +1645,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | |||
1756 | } | 1645 | } |
1757 | EXPORT_SYMBOL (usb_create_hcd); | 1646 | EXPORT_SYMBOL (usb_create_hcd); |
1758 | 1647 | ||
1648 | static void hcd_release (struct kref *kref) | ||
1649 | { | ||
1650 | struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); | ||
1651 | |||
1652 | kfree(hcd); | ||
1653 | } | ||
1654 | |||
1655 | struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd) | ||
1656 | { | ||
1657 | if (hcd) | ||
1658 | kref_get (&hcd->kref); | ||
1659 | return hcd; | ||
1660 | } | ||
1661 | EXPORT_SYMBOL (usb_get_hcd); | ||
1662 | |||
1759 | void usb_put_hcd (struct usb_hcd *hcd) | 1663 | void usb_put_hcd (struct usb_hcd *hcd) |
1760 | { | 1664 | { |
1761 | dev_set_drvdata(hcd->self.controller, NULL); | 1665 | if (hcd) |
1762 | usb_bus_put(&hcd->self); | 1666 | kref_put (&hcd->kref, hcd_release); |
1763 | } | 1667 | } |
1764 | EXPORT_SYMBOL (usb_put_hcd); | 1668 | EXPORT_SYMBOL (usb_put_hcd); |
1765 | 1669 | ||
@@ -1915,6 +1819,16 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
1915 | } | 1819 | } |
1916 | EXPORT_SYMBOL (usb_remove_hcd); | 1820 | EXPORT_SYMBOL (usb_remove_hcd); |
1917 | 1821 | ||
1822 | void | ||
1823 | usb_hcd_platform_shutdown(struct platform_device* dev) | ||
1824 | { | ||
1825 | struct usb_hcd *hcd = platform_get_drvdata(dev); | ||
1826 | |||
1827 | if (hcd->driver->shutdown) | ||
1828 | hcd->driver->shutdown(hcd); | ||
1829 | } | ||
1830 | EXPORT_SYMBOL (usb_hcd_platform_shutdown); | ||
1831 | |||
1918 | /*-------------------------------------------------------------------------*/ | 1832 | /*-------------------------------------------------------------------------*/ |
1919 | 1833 | ||
1920 | #if defined(CONFIG_USB_MON) | 1834 | #if defined(CONFIG_USB_MON) |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 7022aafb2ae8..676877c15f81 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -55,12 +55,13 @@ | |||
55 | 55 | ||
56 | /*-------------------------------------------------------------------------*/ | 56 | /*-------------------------------------------------------------------------*/ |
57 | 57 | ||
58 | struct usb_hcd { /* usb_bus.hcpriv points to this */ | 58 | struct usb_hcd { |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * housekeeping | 61 | * housekeeping |
62 | */ | 62 | */ |
63 | struct usb_bus self; /* hcd is-a bus */ | 63 | struct usb_bus self; /* hcd is-a bus */ |
64 | struct kref kref; /* reference counter */ | ||
64 | 65 | ||
65 | const char *product_desc; /* product/vendor string */ | 66 | const char *product_desc; /* product/vendor string */ |
66 | char irq_descr[24]; /* driver + bus # */ | 67 | char irq_descr[24]; /* driver + bus # */ |
@@ -85,6 +86,7 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ | |||
85 | unsigned uses_new_polling:1; | 86 | unsigned uses_new_polling:1; |
86 | unsigned poll_rh:1; /* poll for rh status? */ | 87 | unsigned poll_rh:1; /* poll for rh status? */ |
87 | unsigned poll_pending:1; /* status has changed? */ | 88 | unsigned poll_pending:1; /* status has changed? */ |
89 | unsigned wireless:1; /* Wireless USB HCD */ | ||
88 | 90 | ||
89 | int irq; /* irq allocated */ | 91 | int irq; /* irq allocated */ |
90 | void __iomem *regs; /* device memory/io */ | 92 | void __iomem *regs; /* device memory/io */ |
@@ -128,8 +130,10 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) | |||
128 | return &hcd->self; | 130 | return &hcd->self; |
129 | } | 131 | } |
130 | 132 | ||
131 | 133 | static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus) | |
132 | // urb.hcpriv is really hardware-specific | 134 | { |
135 | return container_of(bus, struct usb_hcd, self); | ||
136 | } | ||
133 | 137 | ||
134 | struct hcd_timeout { /* timeouts we allocate */ | 138 | struct hcd_timeout { /* timeouts we allocate */ |
135 | struct list_head timeout_list; | 139 | struct list_head timeout_list; |
@@ -138,28 +142,6 @@ struct hcd_timeout { /* timeouts we allocate */ | |||
138 | 142 | ||
139 | /*-------------------------------------------------------------------------*/ | 143 | /*-------------------------------------------------------------------------*/ |
140 | 144 | ||
141 | /* | ||
142 | * FIXME usb_operations should vanish or become hc_driver, | ||
143 | * when usb_bus and usb_hcd become the same thing. | ||
144 | */ | ||
145 | |||
146 | struct usb_operations { | ||
147 | int (*get_frame_number) (struct usb_device *usb_dev); | ||
148 | int (*submit_urb) (struct urb *urb, gfp_t mem_flags); | ||
149 | int (*unlink_urb) (struct urb *urb, int status); | ||
150 | |||
151 | /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */ | ||
152 | void *(*buffer_alloc)(struct usb_bus *bus, size_t size, | ||
153 | gfp_t mem_flags, | ||
154 | dma_addr_t *dma); | ||
155 | void (*buffer_free)(struct usb_bus *bus, size_t size, | ||
156 | void *addr, dma_addr_t dma); | ||
157 | |||
158 | void (*disable)(struct usb_device *udev, | ||
159 | struct usb_host_endpoint *ep); | ||
160 | }; | ||
161 | |||
162 | /* each driver provides one of these, and hardware init support */ | ||
163 | 145 | ||
164 | struct pt_regs; | 146 | struct pt_regs; |
165 | 147 | ||
@@ -192,6 +174,9 @@ struct hc_driver { | |||
192 | /* cleanly make HCD stop writing memory and doing I/O */ | 174 | /* cleanly make HCD stop writing memory and doing I/O */ |
193 | void (*stop) (struct usb_hcd *hcd); | 175 | void (*stop) (struct usb_hcd *hcd); |
194 | 176 | ||
177 | /* shutdown HCD */ | ||
178 | void (*shutdown) (struct usb_hcd *hcd); | ||
179 | |||
195 | /* return current frame number */ | 180 | /* return current frame number */ |
196 | int (*get_frame_number) (struct usb_hcd *hcd); | 181 | int (*get_frame_number) (struct usb_hcd *hcd); |
197 | 182 | ||
@@ -218,15 +203,25 @@ struct hc_driver { | |||
218 | /* Needed only if port-change IRQs are level-triggered */ | 203 | /* Needed only if port-change IRQs are level-triggered */ |
219 | }; | 204 | }; |
220 | 205 | ||
221 | extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); | 206 | extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags); |
207 | extern int usb_hcd_unlink_urb (struct urb *urb, int status); | ||
208 | extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, | ||
209 | struct pt_regs *regs); | ||
210 | extern void usb_hcd_endpoint_disable (struct usb_device *udev, | ||
211 | struct usb_host_endpoint *ep); | ||
212 | extern int usb_hcd_get_frame_number (struct usb_device *udev); | ||
222 | 213 | ||
223 | extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | 214 | extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, |
224 | struct device *dev, char *bus_name); | 215 | struct device *dev, char *bus_name); |
216 | extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd); | ||
225 | extern void usb_put_hcd (struct usb_hcd *hcd); | 217 | extern void usb_put_hcd (struct usb_hcd *hcd); |
226 | extern int usb_add_hcd(struct usb_hcd *hcd, | 218 | extern int usb_add_hcd(struct usb_hcd *hcd, |
227 | unsigned int irqnum, unsigned long irqflags); | 219 | unsigned int irqnum, unsigned long irqflags); |
228 | extern void usb_remove_hcd(struct usb_hcd *hcd); | 220 | extern void usb_remove_hcd(struct usb_hcd *hcd); |
229 | 221 | ||
222 | struct platform_device; | ||
223 | extern void usb_hcd_platform_shutdown(struct platform_device* dev); | ||
224 | |||
230 | #ifdef CONFIG_PCI | 225 | #ifdef CONFIG_PCI |
231 | struct pci_dev; | 226 | struct pci_dev; |
232 | struct pci_device_id; | 227 | struct pci_device_id; |
@@ -239,6 +234,8 @@ extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state); | |||
239 | extern int usb_hcd_pci_resume (struct pci_dev *dev); | 234 | extern int usb_hcd_pci_resume (struct pci_dev *dev); |
240 | #endif /* CONFIG_PM */ | 235 | #endif /* CONFIG_PM */ |
241 | 236 | ||
237 | extern void usb_hcd_pci_shutdown (struct pci_dev *dev); | ||
238 | |||
242 | #endif /* CONFIG_PCI */ | 239 | #endif /* CONFIG_PCI */ |
243 | 240 | ||
244 | /* pci-ish (pdev null is ok) buffer alloc/mapping support */ | 241 | /* pci-ish (pdev null is ok) buffer alloc/mapping support */ |
@@ -352,8 +349,6 @@ extern long usb_calc_bus_time (int speed, int is_input, | |||
352 | 349 | ||
353 | /*-------------------------------------------------------------------------*/ | 350 | /*-------------------------------------------------------------------------*/ |
354 | 351 | ||
355 | extern struct usb_bus *usb_alloc_bus (struct usb_operations *); | ||
356 | |||
357 | extern void usb_set_device_state(struct usb_device *udev, | 352 | extern void usb_set_device_state(struct usb_device *udev, |
358 | enum usb_device_state new_state); | 353 | enum usb_device_state new_state); |
359 | 354 | ||
@@ -365,9 +360,6 @@ extern struct list_head usb_bus_list; | |||
365 | extern struct mutex usb_bus_list_lock; | 360 | extern struct mutex usb_bus_list_lock; |
366 | extern wait_queue_head_t usb_kill_urb_queue; | 361 | extern wait_queue_head_t usb_kill_urb_queue; |
367 | 362 | ||
368 | extern struct usb_bus *usb_bus_get (struct usb_bus *bus); | ||
369 | extern void usb_bus_put (struct usb_bus *bus); | ||
370 | |||
371 | extern void usb_enable_root_hub_irq (struct usb_bus *bus); | 363 | extern void usb_enable_root_hub_irq (struct usb_bus *bus); |
372 | 364 | ||
373 | extern int usb_find_interface_driver (struct usb_device *dev, | 365 | extern int usb_find_interface_driver (struct usb_device *dev, |
@@ -376,17 +368,11 @@ extern int usb_find_interface_driver (struct usb_device *dev, | |||
376 | #define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) | 368 | #define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) |
377 | 369 | ||
378 | #ifdef CONFIG_PM | 370 | #ifdef CONFIG_PM |
379 | extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd); | ||
380 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); | 371 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); |
381 | extern void usb_root_hub_lost_power (struct usb_device *rhdev); | 372 | extern void usb_root_hub_lost_power (struct usb_device *rhdev); |
382 | extern int hcd_bus_suspend (struct usb_bus *bus); | 373 | extern int hcd_bus_suspend (struct usb_bus *bus); |
383 | extern int hcd_bus_resume (struct usb_bus *bus); | 374 | extern int hcd_bus_resume (struct usb_bus *bus); |
384 | #else | 375 | #else |
385 | static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd) | ||
386 | { | ||
387 | return; | ||
388 | } | ||
389 | |||
390 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) | 376 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) |
391 | { | 377 | { |
392 | return; | 378 | return; |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 26c8cb5f3e67..2a8cb3c2b19c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -293,7 +293,7 @@ void usb_kick_khubd(struct usb_device *hdev) | |||
293 | /* completion function, fires on port status changes and various faults */ | 293 | /* completion function, fires on port status changes and various faults */ |
294 | static void hub_irq(struct urb *urb, struct pt_regs *regs) | 294 | static void hub_irq(struct urb *urb, struct pt_regs *regs) |
295 | { | 295 | { |
296 | struct usb_hub *hub = (struct usb_hub *)urb->context; | 296 | struct usb_hub *hub = urb->context; |
297 | int status; | 297 | int status; |
298 | int i; | 298 | int i; |
299 | unsigned long bits; | 299 | unsigned long bits; |
@@ -311,7 +311,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs) | |||
311 | goto resubmit; | 311 | goto resubmit; |
312 | hub->error = urb->status; | 312 | hub->error = urb->status; |
313 | /* FALL THROUGH */ | 313 | /* FALL THROUGH */ |
314 | 314 | ||
315 | /* let khubd handle things */ | 315 | /* let khubd handle things */ |
316 | case 0: /* we got data: port status changed */ | 316 | case 0: /* we got data: port status changed */ |
317 | bits = 0; | 317 | bits = 0; |
@@ -452,18 +452,14 @@ static void hub_power_on(struct usb_hub *hub) | |||
452 | msleep(max(pgood_delay, (unsigned) 100)); | 452 | msleep(max(pgood_delay, (unsigned) 100)); |
453 | } | 453 | } |
454 | 454 | ||
455 | static inline void __hub_quiesce(struct usb_hub *hub) | 455 | static void hub_quiesce(struct usb_hub *hub) |
456 | { | 456 | { |
457 | /* (nonblocking) khubd and related activity won't re-trigger */ | 457 | /* (nonblocking) khubd and related activity won't re-trigger */ |
458 | hub->quiescing = 1; | 458 | hub->quiescing = 1; |
459 | hub->activating = 0; | 459 | hub->activating = 0; |
460 | hub->resume_root_hub = 0; | 460 | hub->resume_root_hub = 0; |
461 | } | ||
462 | 461 | ||
463 | static void hub_quiesce(struct usb_hub *hub) | ||
464 | { | ||
465 | /* (blocking) stop khubd and related activity */ | 462 | /* (blocking) stop khubd and related activity */ |
466 | __hub_quiesce(hub); | ||
467 | usb_kill_urb(hub->urb); | 463 | usb_kill_urb(hub->urb); |
468 | if (hub->has_indicators) | 464 | if (hub->has_indicators) |
469 | cancel_delayed_work(&hub->leds); | 465 | cancel_delayed_work(&hub->leds); |
@@ -868,13 +864,8 @@ descriptor_error: | |||
868 | 864 | ||
869 | endpoint = &desc->endpoint[0].desc; | 865 | endpoint = &desc->endpoint[0].desc; |
870 | 866 | ||
871 | /* Output endpoint? Curiouser and curiouser.. */ | 867 | /* If it's not an interrupt in endpoint, we'd better punt! */ |
872 | if (!(endpoint->bEndpointAddress & USB_DIR_IN)) | 868 | if (!usb_endpoint_is_int_in(endpoint)) |
873 | goto descriptor_error; | ||
874 | |||
875 | /* If it's not an interrupt endpoint, we'd better punt! */ | ||
876 | if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
877 | != USB_ENDPOINT_XFER_INT) | ||
878 | goto descriptor_error; | 869 | goto descriptor_error; |
879 | 870 | ||
880 | /* We found a hub */ | 871 | /* We found a hub */ |
@@ -1022,26 +1013,29 @@ void usb_set_device_state(struct usb_device *udev, | |||
1022 | if (udev->state == USB_STATE_NOTATTACHED) | 1013 | if (udev->state == USB_STATE_NOTATTACHED) |
1023 | ; /* do nothing */ | 1014 | ; /* do nothing */ |
1024 | else if (new_state != USB_STATE_NOTATTACHED) { | 1015 | else if (new_state != USB_STATE_NOTATTACHED) { |
1025 | udev->state = new_state; | ||
1026 | 1016 | ||
1027 | /* root hub wakeup capabilities are managed out-of-band | 1017 | /* root hub wakeup capabilities are managed out-of-band |
1028 | * and may involve silicon errata ... ignore them here. | 1018 | * and may involve silicon errata ... ignore them here. |
1029 | */ | 1019 | */ |
1030 | if (udev->parent) { | 1020 | if (udev->parent) { |
1031 | if (new_state == USB_STATE_CONFIGURED) | 1021 | if (udev->state == USB_STATE_SUSPENDED |
1022 | || new_state == USB_STATE_SUSPENDED) | ||
1023 | ; /* No change to wakeup settings */ | ||
1024 | else if (new_state == USB_STATE_CONFIGURED) | ||
1032 | device_init_wakeup(&udev->dev, | 1025 | device_init_wakeup(&udev->dev, |
1033 | (udev->actconfig->desc.bmAttributes | 1026 | (udev->actconfig->desc.bmAttributes |
1034 | & USB_CONFIG_ATT_WAKEUP)); | 1027 | & USB_CONFIG_ATT_WAKEUP)); |
1035 | else if (new_state != USB_STATE_SUSPENDED) | 1028 | else |
1036 | device_init_wakeup(&udev->dev, 0); | 1029 | device_init_wakeup(&udev->dev, 0); |
1037 | } | 1030 | } |
1031 | udev->state = new_state; | ||
1038 | } else | 1032 | } else |
1039 | recursively_mark_NOTATTACHED(udev); | 1033 | recursively_mark_NOTATTACHED(udev); |
1040 | spin_unlock_irqrestore(&device_state_lock, flags); | 1034 | spin_unlock_irqrestore(&device_state_lock, flags); |
1041 | } | 1035 | } |
1042 | 1036 | ||
1043 | 1037 | ||
1044 | #ifdef CONFIG_PM | 1038 | #ifdef CONFIG_PM |
1045 | 1039 | ||
1046 | /** | 1040 | /** |
1047 | * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power | 1041 | * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power |
@@ -1059,6 +1053,12 @@ void usb_root_hub_lost_power(struct usb_device *rhdev) | |||
1059 | unsigned long flags; | 1053 | unsigned long flags; |
1060 | 1054 | ||
1061 | dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); | 1055 | dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); |
1056 | |||
1057 | /* Make sure no potential wakeup events get lost, | ||
1058 | * by forcing the root hub to be resumed. | ||
1059 | */ | ||
1060 | rhdev->dev.power.prev_state.event = PM_EVENT_ON; | ||
1061 | |||
1062 | spin_lock_irqsave(&device_state_lock, flags); | 1062 | spin_lock_irqsave(&device_state_lock, flags); |
1063 | hub = hdev_to_hub(rhdev); | 1063 | hub = hdev_to_hub(rhdev); |
1064 | for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { | 1064 | for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { |
@@ -1072,7 +1072,7 @@ void usb_root_hub_lost_power(struct usb_device *rhdev) | |||
1072 | } | 1072 | } |
1073 | EXPORT_SYMBOL_GPL(usb_root_hub_lost_power); | 1073 | EXPORT_SYMBOL_GPL(usb_root_hub_lost_power); |
1074 | 1074 | ||
1075 | #endif | 1075 | #endif /* CONFIG_PM */ |
1076 | 1076 | ||
1077 | static void choose_address(struct usb_device *udev) | 1077 | static void choose_address(struct usb_device *udev) |
1078 | { | 1078 | { |
@@ -1148,144 +1148,28 @@ void usb_disconnect(struct usb_device **pdev) | |||
1148 | * cleaning up all state associated with the current configuration | 1148 | * cleaning up all state associated with the current configuration |
1149 | * so that the hardware is now fully quiesced. | 1149 | * so that the hardware is now fully quiesced. |
1150 | */ | 1150 | */ |
1151 | dev_dbg (&udev->dev, "unregistering device\n"); | ||
1151 | usb_disable_device(udev, 0); | 1152 | usb_disable_device(udev, 0); |
1152 | 1153 | ||
1153 | usb_notify_remove_device(udev); | 1154 | usb_unlock_device(udev); |
1154 | 1155 | ||
1155 | /* Free the device number, remove the /proc/bus/usb entry and | 1156 | /* Unregister the device. The device driver is responsible |
1156 | * the sysfs attributes, and delete the parent's children[] | 1157 | * for removing the device files from usbfs and sysfs and for |
1158 | * de-configuring the device. | ||
1159 | */ | ||
1160 | device_del(&udev->dev); | ||
1161 | |||
1162 | /* Free the device number and delete the parent's children[] | ||
1157 | * (or root_hub) pointer. | 1163 | * (or root_hub) pointer. |
1158 | */ | 1164 | */ |
1159 | dev_dbg (&udev->dev, "unregistering device\n"); | ||
1160 | release_address(udev); | 1165 | release_address(udev); |
1161 | usb_remove_sysfs_dev_files(udev); | ||
1162 | 1166 | ||
1163 | /* Avoid races with recursively_mark_NOTATTACHED() */ | 1167 | /* Avoid races with recursively_mark_NOTATTACHED() */ |
1164 | spin_lock_irq(&device_state_lock); | 1168 | spin_lock_irq(&device_state_lock); |
1165 | *pdev = NULL; | 1169 | *pdev = NULL; |
1166 | spin_unlock_irq(&device_state_lock); | 1170 | spin_unlock_irq(&device_state_lock); |
1167 | 1171 | ||
1168 | usb_unlock_device(udev); | 1172 | put_device(&udev->dev); |
1169 | |||
1170 | device_unregister(&udev->dev); | ||
1171 | } | ||
1172 | |||
1173 | static inline const char *plural(int n) | ||
1174 | { | ||
1175 | return (n == 1 ? "" : "s"); | ||
1176 | } | ||
1177 | |||
1178 | static int choose_configuration(struct usb_device *udev) | ||
1179 | { | ||
1180 | int i; | ||
1181 | int num_configs; | ||
1182 | int insufficient_power = 0; | ||
1183 | struct usb_host_config *c, *best; | ||
1184 | |||
1185 | best = NULL; | ||
1186 | c = udev->config; | ||
1187 | num_configs = udev->descriptor.bNumConfigurations; | ||
1188 | for (i = 0; i < num_configs; (i++, c++)) { | ||
1189 | struct usb_interface_descriptor *desc = NULL; | ||
1190 | |||
1191 | /* It's possible that a config has no interfaces! */ | ||
1192 | if (c->desc.bNumInterfaces > 0) | ||
1193 | desc = &c->intf_cache[0]->altsetting->desc; | ||
1194 | |||
1195 | /* | ||
1196 | * HP's USB bus-powered keyboard has only one configuration | ||
1197 | * and it claims to be self-powered; other devices may have | ||
1198 | * similar errors in their descriptors. If the next test | ||
1199 | * were allowed to execute, such configurations would always | ||
1200 | * be rejected and the devices would not work as expected. | ||
1201 | * In the meantime, we run the risk of selecting a config | ||
1202 | * that requires external power at a time when that power | ||
1203 | * isn't available. It seems to be the lesser of two evils. | ||
1204 | * | ||
1205 | * Bugzilla #6448 reports a device that appears to crash | ||
1206 | * when it receives a GET_DEVICE_STATUS request! We don't | ||
1207 | * have any other way to tell whether a device is self-powered, | ||
1208 | * but since we don't use that information anywhere but here, | ||
1209 | * the call has been removed. | ||
1210 | * | ||
1211 | * Maybe the GET_DEVICE_STATUS call and the test below can | ||
1212 | * be reinstated when device firmwares become more reliable. | ||
1213 | * Don't hold your breath. | ||
1214 | */ | ||
1215 | #if 0 | ||
1216 | /* Rule out self-powered configs for a bus-powered device */ | ||
1217 | if (bus_powered && (c->desc.bmAttributes & | ||
1218 | USB_CONFIG_ATT_SELFPOWER)) | ||
1219 | continue; | ||
1220 | #endif | ||
1221 | |||
1222 | /* | ||
1223 | * The next test may not be as effective as it should be. | ||
1224 | * Some hubs have errors in their descriptor, claiming | ||
1225 | * to be self-powered when they are really bus-powered. | ||
1226 | * We will overestimate the amount of current such hubs | ||
1227 | * make available for each port. | ||
1228 | * | ||
1229 | * This is a fairly benign sort of failure. It won't | ||
1230 | * cause us to reject configurations that we should have | ||
1231 | * accepted. | ||
1232 | */ | ||
1233 | |||
1234 | /* Rule out configs that draw too much bus current */ | ||
1235 | if (c->desc.bMaxPower * 2 > udev->bus_mA) { | ||
1236 | insufficient_power++; | ||
1237 | continue; | ||
1238 | } | ||
1239 | |||
1240 | /* If the first config's first interface is COMM/2/0xff | ||
1241 | * (MSFT RNDIS), rule it out unless Linux has host-side | ||
1242 | * RNDIS support. */ | ||
1243 | if (i == 0 && desc | ||
1244 | && desc->bInterfaceClass == USB_CLASS_COMM | ||
1245 | && desc->bInterfaceSubClass == 2 | ||
1246 | && desc->bInterfaceProtocol == 0xff) { | ||
1247 | #ifndef CONFIG_USB_NET_RNDIS_HOST | ||
1248 | continue; | ||
1249 | #else | ||
1250 | best = c; | ||
1251 | #endif | ||
1252 | } | ||
1253 | |||
1254 | /* From the remaining configs, choose the first one whose | ||
1255 | * first interface is for a non-vendor-specific class. | ||
1256 | * Reason: Linux is more likely to have a class driver | ||
1257 | * than a vendor-specific driver. */ | ||
1258 | else if (udev->descriptor.bDeviceClass != | ||
1259 | USB_CLASS_VENDOR_SPEC && | ||
1260 | (!desc || desc->bInterfaceClass != | ||
1261 | USB_CLASS_VENDOR_SPEC)) { | ||
1262 | best = c; | ||
1263 | break; | ||
1264 | } | ||
1265 | |||
1266 | /* If all the remaining configs are vendor-specific, | ||
1267 | * choose the first one. */ | ||
1268 | else if (!best) | ||
1269 | best = c; | ||
1270 | } | ||
1271 | |||
1272 | if (insufficient_power > 0) | ||
1273 | dev_info(&udev->dev, "rejected %d configuration%s " | ||
1274 | "due to insufficient available bus power\n", | ||
1275 | insufficient_power, plural(insufficient_power)); | ||
1276 | |||
1277 | if (best) { | ||
1278 | i = best->desc.bConfigurationValue; | ||
1279 | dev_info(&udev->dev, | ||
1280 | "configuration #%d chosen from %d choice%s\n", | ||
1281 | i, num_configs, plural(num_configs)); | ||
1282 | } else { | ||
1283 | i = -1; | ||
1284 | dev_warn(&udev->dev, | ||
1285 | "no configuration chosen from %d choice%s\n", | ||
1286 | num_configs, plural(num_configs)); | ||
1287 | } | ||
1288 | return i; | ||
1289 | } | 1173 | } |
1290 | 1174 | ||
1291 | #ifdef DEBUG | 1175 | #ifdef DEBUG |
@@ -1328,7 +1212,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) | |||
1328 | int usb_new_device(struct usb_device *udev) | 1212 | int usb_new_device(struct usb_device *udev) |
1329 | { | 1213 | { |
1330 | int err; | 1214 | int err; |
1331 | int c; | ||
1332 | 1215 | ||
1333 | err = usb_get_configuration(udev); | 1216 | err = usb_get_configuration(udev); |
1334 | if (err < 0) { | 1217 | if (err < 0) { |
@@ -1371,8 +1254,7 @@ int usb_new_device(struct usb_device *udev) | |||
1371 | USB_DT_OTG, (void **) &desc) == 0) { | 1254 | USB_DT_OTG, (void **) &desc) == 0) { |
1372 | if (desc->bmAttributes & USB_OTG_HNP) { | 1255 | if (desc->bmAttributes & USB_OTG_HNP) { |
1373 | unsigned port1 = udev->portnum; | 1256 | unsigned port1 = udev->portnum; |
1374 | struct usb_device *root = udev->parent; | 1257 | |
1375 | |||
1376 | dev_info(&udev->dev, | 1258 | dev_info(&udev->dev, |
1377 | "Dual-Role OTG device on %sHNP port\n", | 1259 | "Dual-Role OTG device on %sHNP port\n", |
1378 | (port1 == bus->otg_port) | 1260 | (port1 == bus->otg_port) |
@@ -1407,9 +1289,9 @@ int usb_new_device(struct usb_device *udev) | |||
1407 | * (Includes HNP test device.) | 1289 | * (Includes HNP test device.) |
1408 | */ | 1290 | */ |
1409 | if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { | 1291 | if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { |
1410 | static int __usb_suspend_device(struct usb_device *, | 1292 | static int __usb_port_suspend(struct usb_device *, |
1411 | int port1); | 1293 | int port1); |
1412 | err = __usb_suspend_device(udev, udev->bus->otg_port); | 1294 | err = __usb_port_suspend(udev, udev->bus->otg_port); |
1413 | if (err < 0) | 1295 | if (err < 0) |
1414 | dev_dbg(&udev->dev, "HNP fail, %d\n", err); | 1296 | dev_dbg(&udev->dev, "HNP fail, %d\n", err); |
1415 | } | 1297 | } |
@@ -1418,34 +1300,15 @@ int usb_new_device(struct usb_device *udev) | |||
1418 | } | 1300 | } |
1419 | #endif | 1301 | #endif |
1420 | 1302 | ||
1421 | /* put device-specific files into sysfs */ | 1303 | /* Register the device. The device driver is responsible |
1304 | * for adding the device files to usbfs and sysfs and for | ||
1305 | * configuring the device. | ||
1306 | */ | ||
1422 | err = device_add (&udev->dev); | 1307 | err = device_add (&udev->dev); |
1423 | if (err) { | 1308 | if (err) { |
1424 | dev_err(&udev->dev, "can't device_add, error %d\n", err); | 1309 | dev_err(&udev->dev, "can't device_add, error %d\n", err); |
1425 | goto fail; | 1310 | goto fail; |
1426 | } | 1311 | } |
1427 | usb_create_sysfs_dev_files (udev); | ||
1428 | |||
1429 | usb_lock_device(udev); | ||
1430 | |||
1431 | /* choose and set the configuration. that registers the interfaces | ||
1432 | * with the driver core, and lets usb device drivers bind to them. | ||
1433 | */ | ||
1434 | c = choose_configuration(udev); | ||
1435 | if (c >= 0) { | ||
1436 | err = usb_set_configuration(udev, c); | ||
1437 | if (err) { | ||
1438 | dev_err(&udev->dev, "can't set config #%d, error %d\n", | ||
1439 | c, err); | ||
1440 | /* This need not be fatal. The user can try to | ||
1441 | * set other configurations. */ | ||
1442 | } | ||
1443 | } | ||
1444 | |||
1445 | /* USB device state == configured ... usable */ | ||
1446 | usb_notify_add_device(udev); | ||
1447 | |||
1448 | usb_unlock_device(udev); | ||
1449 | 1312 | ||
1450 | return 0; | 1313 | return 0; |
1451 | 1314 | ||
@@ -1472,6 +1335,18 @@ static int hub_port_status(struct usb_hub *hub, int port1, | |||
1472 | return ret; | 1335 | return ret; |
1473 | } | 1336 | } |
1474 | 1337 | ||
1338 | |||
1339 | /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */ | ||
1340 | static unsigned hub_is_wusb(struct usb_hub *hub) | ||
1341 | { | ||
1342 | struct usb_hcd *hcd; | ||
1343 | if (hub->hdev->parent != NULL) /* not a root hub? */ | ||
1344 | return 0; | ||
1345 | hcd = container_of(hub->hdev->bus, struct usb_hcd, self); | ||
1346 | return hcd->wireless; | ||
1347 | } | ||
1348 | |||
1349 | |||
1475 | #define PORT_RESET_TRIES 5 | 1350 | #define PORT_RESET_TRIES 5 |
1476 | #define SET_ADDRESS_TRIES 2 | 1351 | #define SET_ADDRESS_TRIES 2 |
1477 | #define GET_DESCRIPTOR_TRIES 2 | 1352 | #define GET_DESCRIPTOR_TRIES 2 |
@@ -1512,7 +1387,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
1512 | /* if we`ve finished resetting, then break out of the loop */ | 1387 | /* if we`ve finished resetting, then break out of the loop */ |
1513 | if (!(portstatus & USB_PORT_STAT_RESET) && | 1388 | if (!(portstatus & USB_PORT_STAT_RESET) && |
1514 | (portstatus & USB_PORT_STAT_ENABLE)) { | 1389 | (portstatus & USB_PORT_STAT_ENABLE)) { |
1515 | if (portstatus & USB_PORT_STAT_HIGH_SPEED) | 1390 | if (hub_is_wusb(hub)) |
1391 | udev->speed = USB_SPEED_VARIABLE; | ||
1392 | else if (portstatus & USB_PORT_STAT_HIGH_SPEED) | ||
1516 | udev->speed = USB_SPEED_HIGH; | 1393 | udev->speed = USB_SPEED_HIGH; |
1517 | else if (portstatus & USB_PORT_STAT_LOW_SPEED) | 1394 | else if (portstatus & USB_PORT_STAT_LOW_SPEED) |
1518 | udev->speed = USB_SPEED_LOW; | 1395 | udev->speed = USB_SPEED_LOW; |
@@ -1607,6 +1484,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) | |||
1607 | kick_khubd(hub); | 1484 | kick_khubd(hub); |
1608 | } | 1485 | } |
1609 | 1486 | ||
1487 | #ifdef CONFIG_PM | ||
1610 | 1488 | ||
1611 | #ifdef CONFIG_USB_SUSPEND | 1489 | #ifdef CONFIG_USB_SUSPEND |
1612 | 1490 | ||
@@ -1633,7 +1511,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1, | |||
1633 | * NOTE: OTG devices may issue remote wakeup (or SRP) even when | 1511 | * NOTE: OTG devices may issue remote wakeup (or SRP) even when |
1634 | * we don't explicitly enable it here. | 1512 | * we don't explicitly enable it here. |
1635 | */ | 1513 | */ |
1636 | if (device_may_wakeup(&udev->dev)) { | 1514 | if (udev->do_remote_wakeup) { |
1637 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 1515 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
1638 | USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, | 1516 | USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, |
1639 | USB_DEVICE_REMOTE_WAKEUP, 0, | 1517 | USB_DEVICE_REMOTE_WAKEUP, 0, |
@@ -1659,7 +1537,8 @@ static int hub_port_suspend(struct usb_hub *hub, int port1, | |||
1659 | USB_CTRL_SET_TIMEOUT); | 1537 | USB_CTRL_SET_TIMEOUT); |
1660 | } else { | 1538 | } else { |
1661 | /* device has up to 10 msec to fully suspend */ | 1539 | /* device has up to 10 msec to fully suspend */ |
1662 | dev_dbg(&udev->dev, "usb suspend\n"); | 1540 | dev_dbg(&udev->dev, "usb %ssuspend\n", |
1541 | udev->auto_pm ? "auto-" : ""); | ||
1663 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | 1542 | usb_set_device_state(udev, USB_STATE_SUSPENDED); |
1664 | msleep(10); | 1543 | msleep(10); |
1665 | } | 1544 | } |
@@ -1684,7 +1563,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1, | |||
1684 | * the root hub for their bus goes into global suspend ... so we don't | 1563 | * the root hub for their bus goes into global suspend ... so we don't |
1685 | * (falsely) update the device power state to say it suspended. | 1564 | * (falsely) update the device power state to say it suspended. |
1686 | */ | 1565 | */ |
1687 | static int __usb_suspend_device (struct usb_device *udev, int port1) | 1566 | static int __usb_port_suspend (struct usb_device *udev, int port1) |
1688 | { | 1567 | { |
1689 | int status = 0; | 1568 | int status = 0; |
1690 | 1569 | ||
@@ -1692,49 +1571,29 @@ static int __usb_suspend_device (struct usb_device *udev, int port1) | |||
1692 | if (port1 < 0) | 1571 | if (port1 < 0) |
1693 | return port1; | 1572 | return port1; |
1694 | 1573 | ||
1695 | if (udev->state == USB_STATE_SUSPENDED | 1574 | /* we change the device's upstream USB link, |
1696 | || udev->state == USB_STATE_NOTATTACHED) { | 1575 | * but root hubs have no upstream USB link. |
1697 | return 0; | ||
1698 | } | ||
1699 | |||
1700 | /* all interfaces must already be suspended */ | ||
1701 | if (udev->actconfig) { | ||
1702 | int i; | ||
1703 | |||
1704 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | ||
1705 | struct usb_interface *intf; | ||
1706 | |||
1707 | intf = udev->actconfig->interface[i]; | ||
1708 | if (is_active(intf)) { | ||
1709 | dev_dbg(&intf->dev, "nyet suspended\n"); | ||
1710 | return -EBUSY; | ||
1711 | } | ||
1712 | } | ||
1713 | } | ||
1714 | |||
1715 | /* we only change a device's upstream USB link. | ||
1716 | * root hubs have no upstream USB link. | ||
1717 | */ | 1576 | */ |
1718 | if (udev->parent) | 1577 | if (udev->parent) |
1719 | status = hub_port_suspend(hdev_to_hub(udev->parent), port1, | 1578 | status = hub_port_suspend(hdev_to_hub(udev->parent), port1, |
1720 | udev); | 1579 | udev); |
1721 | 1580 | else { | |
1722 | if (status == 0) | 1581 | dev_dbg(&udev->dev, "usb %ssuspend\n", |
1723 | udev->dev.power.power_state = PMSG_SUSPEND; | 1582 | udev->auto_pm ? "auto-" : ""); |
1583 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | ||
1584 | } | ||
1724 | return status; | 1585 | return status; |
1725 | } | 1586 | } |
1726 | 1587 | ||
1727 | #endif | ||
1728 | |||
1729 | /* | 1588 | /* |
1730 | * usb_suspend_device - suspend a usb device | 1589 | * usb_port_suspend - suspend a usb device's upstream port |
1731 | * @udev: device that's no longer in active use | 1590 | * @udev: device that's no longer in active use |
1732 | * Context: must be able to sleep; device not locked; pm locks held | 1591 | * Context: must be able to sleep; device not locked; pm locks held |
1733 | * | 1592 | * |
1734 | * Suspends a USB device that isn't in active use, conserving power. | 1593 | * Suspends a USB device that isn't in active use, conserving power. |
1735 | * Devices may wake out of a suspend, if anything important happens, | 1594 | * Devices may wake out of a suspend, if anything important happens, |
1736 | * using the remote wakeup mechanism. They may also be taken out of | 1595 | * using the remote wakeup mechanism. They may also be taken out of |
1737 | * suspend by the host, using usb_resume_device(). It's also routine | 1596 | * suspend by the host, using usb_port_resume(). It's also routine |
1738 | * to disconnect devices while they are suspended. | 1597 | * to disconnect devices while they are suspended. |
1739 | * | 1598 | * |
1740 | * This only affects the USB hardware for a device; its interfaces | 1599 | * This only affects the USB hardware for a device; its interfaces |
@@ -1746,17 +1605,9 @@ static int __usb_suspend_device (struct usb_device *udev, int port1) | |||
1746 | * | 1605 | * |
1747 | * Returns 0 on success, else negative errno. | 1606 | * Returns 0 on success, else negative errno. |
1748 | */ | 1607 | */ |
1749 | int usb_suspend_device(struct usb_device *udev) | 1608 | int usb_port_suspend(struct usb_device *udev) |
1750 | { | 1609 | { |
1751 | #ifdef CONFIG_USB_SUSPEND | 1610 | return __usb_port_suspend(udev, udev->portnum); |
1752 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1753 | return -ENODEV; | ||
1754 | return __usb_suspend_device(udev, udev->portnum); | ||
1755 | #else | ||
1756 | /* NOTE: udev->state unchanged, it's not lying ... */ | ||
1757 | udev->dev.power.power_state = PMSG_SUSPEND; | ||
1758 | return 0; | ||
1759 | #endif | ||
1760 | } | 1611 | } |
1761 | 1612 | ||
1762 | /* | 1613 | /* |
@@ -1767,7 +1618,7 @@ int usb_suspend_device(struct usb_device *udev) | |||
1767 | * resume (by host) or remote wakeup (by device) ... now see what changed | 1618 | * resume (by host) or remote wakeup (by device) ... now see what changed |
1768 | * in the tree that's rooted at this device. | 1619 | * in the tree that's rooted at this device. |
1769 | */ | 1620 | */ |
1770 | static int finish_device_resume(struct usb_device *udev) | 1621 | static int finish_port_resume(struct usb_device *udev) |
1771 | { | 1622 | { |
1772 | int status; | 1623 | int status; |
1773 | u16 devstatus; | 1624 | u16 devstatus; |
@@ -1783,7 +1634,6 @@ static int finish_device_resume(struct usb_device *udev) | |||
1783 | usb_set_device_state(udev, udev->actconfig | 1634 | usb_set_device_state(udev, udev->actconfig |
1784 | ? USB_STATE_CONFIGURED | 1635 | ? USB_STATE_CONFIGURED |
1785 | : USB_STATE_ADDRESS); | 1636 | : USB_STATE_ADDRESS); |
1786 | udev->dev.power.power_state = PMSG_ON; | ||
1787 | 1637 | ||
1788 | /* 10.5.4.5 says be sure devices in the tree are still there. | 1638 | /* 10.5.4.5 says be sure devices in the tree are still there. |
1789 | * For now let's assume the device didn't go crazy on resume, | 1639 | * For now let's assume the device didn't go crazy on resume, |
@@ -1798,9 +1648,6 @@ static int finish_device_resume(struct usb_device *udev) | |||
1798 | "gone after usb resume? status %d\n", | 1648 | "gone after usb resume? status %d\n", |
1799 | status); | 1649 | status); |
1800 | else if (udev->actconfig) { | 1650 | else if (udev->actconfig) { |
1801 | unsigned i; | ||
1802 | int (*resume)(struct device *); | ||
1803 | |||
1804 | le16_to_cpus(&devstatus); | 1651 | le16_to_cpus(&devstatus); |
1805 | if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) | 1652 | if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) |
1806 | && udev->parent) { | 1653 | && udev->parent) { |
@@ -1811,24 +1658,9 @@ static int finish_device_resume(struct usb_device *udev) | |||
1811 | USB_DEVICE_REMOTE_WAKEUP, 0, | 1658 | USB_DEVICE_REMOTE_WAKEUP, 0, |
1812 | NULL, 0, | 1659 | NULL, 0, |
1813 | USB_CTRL_SET_TIMEOUT); | 1660 | USB_CTRL_SET_TIMEOUT); |
1814 | if (status) { | 1661 | if (status) |
1815 | dev_dbg(&udev->dev, "disable remote " | 1662 | dev_dbg(&udev->dev, "disable remote " |
1816 | "wakeup, status %d\n", status); | 1663 | "wakeup, status %d\n", status); |
1817 | status = 0; | ||
1818 | } | ||
1819 | } | ||
1820 | |||
1821 | /* resume interface drivers; if this is a hub, it | ||
1822 | * may have a child resume event to deal with soon | ||
1823 | */ | ||
1824 | resume = udev->dev.bus->resume; | ||
1825 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | ||
1826 | struct device *dev = | ||
1827 | &udev->actconfig->interface[i]->dev; | ||
1828 | |||
1829 | down(&dev->sem); | ||
1830 | (void) resume(dev); | ||
1831 | up(&dev->sem); | ||
1832 | } | 1664 | } |
1833 | status = 0; | 1665 | status = 0; |
1834 | 1666 | ||
@@ -1839,8 +1671,6 @@ static int finish_device_resume(struct usb_device *udev) | |||
1839 | return status; | 1671 | return status; |
1840 | } | 1672 | } |
1841 | 1673 | ||
1842 | #ifdef CONFIG_USB_SUSPEND | ||
1843 | |||
1844 | static int | 1674 | static int |
1845 | hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | 1675 | hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) |
1846 | { | 1676 | { |
@@ -1848,6 +1678,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | |||
1848 | 1678 | ||
1849 | // dev_dbg(hub->intfdev, "resume port %d\n", port1); | 1679 | // dev_dbg(hub->intfdev, "resume port %d\n", port1); |
1850 | 1680 | ||
1681 | set_bit(port1, hub->busy_bits); | ||
1682 | |||
1851 | /* see 7.1.7.7; affects power usage, but not budgeting */ | 1683 | /* see 7.1.7.7; affects power usage, but not budgeting */ |
1852 | status = clear_port_feature(hub->hdev, | 1684 | status = clear_port_feature(hub->hdev, |
1853 | port1, USB_PORT_FEAT_SUSPEND); | 1685 | port1, USB_PORT_FEAT_SUSPEND); |
@@ -1861,7 +1693,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | |||
1861 | 1693 | ||
1862 | /* drive resume for at least 20 msec */ | 1694 | /* drive resume for at least 20 msec */ |
1863 | if (udev) | 1695 | if (udev) |
1864 | dev_dbg(&udev->dev, "RESUME\n"); | 1696 | dev_dbg(&udev->dev, "usb %sresume\n", |
1697 | udev->auto_pm ? "auto-" : ""); | ||
1865 | msleep(25); | 1698 | msleep(25); |
1866 | 1699 | ||
1867 | #define LIVE_FLAGS ( USB_PORT_STAT_POWER \ | 1700 | #define LIVE_FLAGS ( USB_PORT_STAT_POWER \ |
@@ -1891,19 +1724,21 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | |||
1891 | /* TRSMRCY = 10 msec */ | 1724 | /* TRSMRCY = 10 msec */ |
1892 | msleep(10); | 1725 | msleep(10); |
1893 | if (udev) | 1726 | if (udev) |
1894 | status = finish_device_resume(udev); | 1727 | status = finish_port_resume(udev); |
1895 | } | 1728 | } |
1896 | } | 1729 | } |
1897 | if (status < 0) | 1730 | if (status < 0) |
1898 | hub_port_logical_disconnect(hub, port1); | 1731 | hub_port_logical_disconnect(hub, port1); |
1899 | 1732 | ||
1733 | clear_bit(port1, hub->busy_bits); | ||
1734 | if (!hub->hdev->parent && !hub->busy_bits[0]) | ||
1735 | usb_enable_root_hub_irq(hub->hdev->bus); | ||
1736 | |||
1900 | return status; | 1737 | return status; |
1901 | } | 1738 | } |
1902 | 1739 | ||
1903 | #endif | ||
1904 | |||
1905 | /* | 1740 | /* |
1906 | * usb_resume_device - re-activate a suspended usb device | 1741 | * usb_port_resume - re-activate a suspended usb device's upstream port |
1907 | * @udev: device to re-activate | 1742 | * @udev: device to re-activate |
1908 | * Context: must be able to sleep; device not locked; pm locks held | 1743 | * Context: must be able to sleep; device not locked; pm locks held |
1909 | * | 1744 | * |
@@ -1915,36 +1750,24 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | |||
1915 | * | 1750 | * |
1916 | * Returns 0 on success, else negative errno. | 1751 | * Returns 0 on success, else negative errno. |
1917 | */ | 1752 | */ |
1918 | int usb_resume_device(struct usb_device *udev) | 1753 | int usb_port_resume(struct usb_device *udev) |
1919 | { | 1754 | { |
1920 | int status; | 1755 | int status; |
1921 | 1756 | ||
1922 | if (udev->state == USB_STATE_NOTATTACHED) | 1757 | /* we change the device's upstream USB link, |
1923 | return -ENODEV; | 1758 | * but root hubs have no upstream USB link. |
1924 | 1759 | */ | |
1925 | /* selective resume of one downstream hub-to-device port */ | ||
1926 | if (udev->parent) { | 1760 | if (udev->parent) { |
1927 | #ifdef CONFIG_USB_SUSPEND | 1761 | // NOTE this fails if parent is also suspended... |
1928 | if (udev->state == USB_STATE_SUSPENDED) { | 1762 | status = hub_port_resume(hdev_to_hub(udev->parent), |
1929 | // NOTE swsusp may bork us, device state being wrong... | 1763 | udev->portnum, udev); |
1930 | // NOTE this fails if parent is also suspended... | 1764 | } else { |
1931 | status = hub_port_resume(hdev_to_hub(udev->parent), | 1765 | dev_dbg(&udev->dev, "usb %sresume\n", |
1932 | udev->portnum, udev); | 1766 | udev->auto_pm ? "auto-" : ""); |
1933 | } else | 1767 | status = finish_port_resume(udev); |
1934 | #endif | ||
1935 | status = 0; | ||
1936 | } else | ||
1937 | status = finish_device_resume(udev); | ||
1938 | if (status < 0) | ||
1939 | dev_dbg(&udev->dev, "can't resume, status %d\n", | ||
1940 | status); | ||
1941 | |||
1942 | /* rebind drivers that had no suspend() */ | ||
1943 | if (status == 0) { | ||
1944 | usb_unlock_device(udev); | ||
1945 | bus_rescan_devices(&usb_bus_type); | ||
1946 | usb_lock_device(udev); | ||
1947 | } | 1768 | } |
1769 | if (status < 0) | ||
1770 | dev_dbg(&udev->dev, "can't resume, status %d\n", status); | ||
1948 | return status; | 1771 | return status; |
1949 | } | 1772 | } |
1950 | 1773 | ||
@@ -1952,23 +1775,60 @@ static int remote_wakeup(struct usb_device *udev) | |||
1952 | { | 1775 | { |
1953 | int status = 0; | 1776 | int status = 0; |
1954 | 1777 | ||
1955 | #ifdef CONFIG_USB_SUSPEND | 1778 | /* All this just to avoid sending a port-resume message |
1779 | * to the parent hub! */ | ||
1956 | 1780 | ||
1957 | /* don't repeat RESUME sequence if this device | ||
1958 | * was already woken up by some other task | ||
1959 | */ | ||
1960 | usb_lock_device(udev); | 1781 | usb_lock_device(udev); |
1782 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
1961 | if (udev->state == USB_STATE_SUSPENDED) { | 1783 | if (udev->state == USB_STATE_SUSPENDED) { |
1962 | dev_dbg(&udev->dev, "RESUME (wakeup)\n"); | 1784 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); |
1963 | /* TRSMRCY = 10 msec */ | 1785 | /* TRSMRCY = 10 msec */ |
1964 | msleep(10); | 1786 | msleep(10); |
1965 | status = finish_device_resume(udev); | 1787 | status = finish_port_resume(udev); |
1788 | if (status == 0) | ||
1789 | udev->dev.power.power_state.event = PM_EVENT_ON; | ||
1966 | } | 1790 | } |
1791 | mutex_unlock(&udev->pm_mutex); | ||
1792 | |||
1793 | if (status == 0) | ||
1794 | usb_autoresume_device(udev, 0); | ||
1967 | usb_unlock_device(udev); | 1795 | usb_unlock_device(udev); |
1968 | #endif | ||
1969 | return status; | 1796 | return status; |
1970 | } | 1797 | } |
1971 | 1798 | ||
1799 | #else /* CONFIG_USB_SUSPEND */ | ||
1800 | |||
1801 | /* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ | ||
1802 | |||
1803 | int usb_port_suspend(struct usb_device *udev) | ||
1804 | { | ||
1805 | return 0; | ||
1806 | } | ||
1807 | |||
1808 | static inline int | ||
1809 | finish_port_resume(struct usb_device *udev) | ||
1810 | { | ||
1811 | return 0; | ||
1812 | } | ||
1813 | |||
1814 | static inline int | ||
1815 | hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | ||
1816 | { | ||
1817 | return 0; | ||
1818 | } | ||
1819 | |||
1820 | int usb_port_resume(struct usb_device *udev) | ||
1821 | { | ||
1822 | return 0; | ||
1823 | } | ||
1824 | |||
1825 | static inline int remote_wakeup(struct usb_device *udev) | ||
1826 | { | ||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | #endif | ||
1831 | |||
1972 | static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | 1832 | static int hub_suspend(struct usb_interface *intf, pm_message_t msg) |
1973 | { | 1833 | { |
1974 | struct usb_hub *hub = usb_get_intfdata (intf); | 1834 | struct usb_hub *hub = usb_get_intfdata (intf); |
@@ -1980,13 +1840,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
1980 | struct usb_device *udev; | 1840 | struct usb_device *udev; |
1981 | 1841 | ||
1982 | udev = hdev->children [port1-1]; | 1842 | udev = hdev->children [port1-1]; |
1983 | if (udev && (udev->dev.power.power_state.event | 1843 | if (udev && msg.event == PM_EVENT_SUSPEND && |
1984 | == PM_EVENT_ON | ||
1985 | #ifdef CONFIG_USB_SUSPEND | 1844 | #ifdef CONFIG_USB_SUSPEND |
1986 | || udev->state != USB_STATE_SUSPENDED | 1845 | udev->state != USB_STATE_SUSPENDED |
1846 | #else | ||
1847 | udev->dev.power.power_state.event | ||
1848 | == PM_EVENT_ON | ||
1987 | #endif | 1849 | #endif |
1988 | )) { | 1850 | ) { |
1989 | dev_dbg(&intf->dev, "port %d nyet suspended\n", port1); | 1851 | if (!hdev->auto_pm) |
1852 | dev_dbg(&intf->dev, "port %d nyet suspended\n", | ||
1853 | port1); | ||
1990 | return -EBUSY; | 1854 | return -EBUSY; |
1991 | } | 1855 | } |
1992 | } | 1856 | } |
@@ -2035,66 +1899,22 @@ static int hub_resume(struct usb_interface *intf) | |||
2035 | } | 1899 | } |
2036 | } | 1900 | } |
2037 | 1901 | ||
1902 | /* tell khubd to look for changes on this hub */ | ||
2038 | hub_activate(hub); | 1903 | hub_activate(hub); |
2039 | |||
2040 | /* REVISIT: this recursion probably shouldn't exist. Remove | ||
2041 | * this code sometime, after retesting with different root and | ||
2042 | * external hubs. | ||
2043 | */ | ||
2044 | #ifdef CONFIG_USB_SUSPEND | ||
2045 | { | ||
2046 | unsigned port1; | ||
2047 | |||
2048 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | ||
2049 | struct usb_device *udev; | ||
2050 | u16 portstat, portchange; | ||
2051 | |||
2052 | udev = hdev->children [port1-1]; | ||
2053 | status = hub_port_status(hub, port1, &portstat, &portchange); | ||
2054 | if (status == 0) { | ||
2055 | if (portchange & USB_PORT_STAT_C_SUSPEND) { | ||
2056 | clear_port_feature(hdev, port1, | ||
2057 | USB_PORT_FEAT_C_SUSPEND); | ||
2058 | portchange &= ~USB_PORT_STAT_C_SUSPEND; | ||
2059 | } | ||
2060 | |||
2061 | /* let khubd handle disconnects etc */ | ||
2062 | if (portchange) | ||
2063 | continue; | ||
2064 | } | ||
2065 | |||
2066 | if (!udev || status < 0) | ||
2067 | continue; | ||
2068 | usb_lock_device(udev); | ||
2069 | if (portstat & USB_PORT_STAT_SUSPEND) | ||
2070 | status = hub_port_resume(hub, port1, udev); | ||
2071 | else { | ||
2072 | status = finish_device_resume(udev); | ||
2073 | if (status < 0) { | ||
2074 | dev_dbg(&intf->dev, "resume port %d --> %d\n", | ||
2075 | port1, status); | ||
2076 | hub_port_logical_disconnect(hub, port1); | ||
2077 | } | ||
2078 | } | ||
2079 | usb_unlock_device(udev); | ||
2080 | } | ||
2081 | } | ||
2082 | #endif | ||
2083 | return 0; | 1904 | return 0; |
2084 | } | 1905 | } |
2085 | 1906 | ||
2086 | void usb_suspend_root_hub(struct usb_device *hdev) | 1907 | #else /* CONFIG_PM */ |
2087 | { | ||
2088 | struct usb_hub *hub = hdev_to_hub(hdev); | ||
2089 | 1908 | ||
2090 | /* This also makes any led blinker stop retriggering. We're called | 1909 | static inline int remote_wakeup(struct usb_device *udev) |
2091 | * from irq, so the blinker might still be scheduled. Caller promises | 1910 | { |
2092 | * that the root hub status URB will be canceled. | 1911 | return 0; |
2093 | */ | ||
2094 | __hub_quiesce(hub); | ||
2095 | mark_quiesced(to_usb_interface(hub->intfdev)); | ||
2096 | } | 1912 | } |
2097 | 1913 | ||
1914 | #define hub_suspend NULL | ||
1915 | #define hub_resume NULL | ||
1916 | #endif | ||
1917 | |||
2098 | void usb_resume_root_hub(struct usb_device *hdev) | 1918 | void usb_resume_root_hub(struct usb_device *hdev) |
2099 | { | 1919 | { |
2100 | struct usb_hub *hub = hdev_to_hub(hdev); | 1920 | struct usb_hub *hub = hdev_to_hub(hdev); |
@@ -2214,6 +2034,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2214 | int i, j, retval; | 2034 | int i, j, retval; |
2215 | unsigned delay = HUB_SHORT_RESET_TIME; | 2035 | unsigned delay = HUB_SHORT_RESET_TIME; |
2216 | enum usb_device_speed oldspeed = udev->speed; | 2036 | enum usb_device_speed oldspeed = udev->speed; |
2037 | char *speed, *type; | ||
2217 | 2038 | ||
2218 | /* root hub ports have a slightly longer reset period | 2039 | /* root hub ports have a slightly longer reset period |
2219 | * (from USB 2.0 spec, section 7.1.7.5) | 2040 | * (from USB 2.0 spec, section 7.1.7.5) |
@@ -2246,8 +2067,13 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2246 | 2067 | ||
2247 | /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... | 2068 | /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... |
2248 | * it's fixed size except for full speed devices. | 2069 | * it's fixed size except for full speed devices. |
2070 | * For Wireless USB devices, ep0 max packet is always 512 (tho | ||
2071 | * reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. | ||
2249 | */ | 2072 | */ |
2250 | switch (udev->speed) { | 2073 | switch (udev->speed) { |
2074 | case USB_SPEED_VARIABLE: /* fixed at 512 */ | ||
2075 | udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512); | ||
2076 | break; | ||
2251 | case USB_SPEED_HIGH: /* fixed at 64 */ | 2077 | case USB_SPEED_HIGH: /* fixed at 64 */ |
2252 | udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); | 2078 | udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); |
2253 | break; | 2079 | break; |
@@ -2265,17 +2091,21 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2265 | goto fail; | 2091 | goto fail; |
2266 | } | 2092 | } |
2267 | 2093 | ||
2094 | type = ""; | ||
2095 | switch (udev->speed) { | ||
2096 | case USB_SPEED_LOW: speed = "low"; break; | ||
2097 | case USB_SPEED_FULL: speed = "full"; break; | ||
2098 | case USB_SPEED_HIGH: speed = "high"; break; | ||
2099 | case USB_SPEED_VARIABLE: | ||
2100 | speed = "variable"; | ||
2101 | type = "Wireless "; | ||
2102 | break; | ||
2103 | default: speed = "?"; break; | ||
2104 | } | ||
2268 | dev_info (&udev->dev, | 2105 | dev_info (&udev->dev, |
2269 | "%s %s speed USB device using %s and address %d\n", | 2106 | "%s %s speed %sUSB device using %s and address %d\n", |
2270 | (udev->config) ? "reset" : "new", | 2107 | (udev->config) ? "reset" : "new", speed, type, |
2271 | ({ char *speed; switch (udev->speed) { | 2108 | udev->bus->controller->driver->name, udev->devnum); |
2272 | case USB_SPEED_LOW: speed = "low"; break; | ||
2273 | case USB_SPEED_FULL: speed = "full"; break; | ||
2274 | case USB_SPEED_HIGH: speed = "high"; break; | ||
2275 | default: speed = "?"; break; | ||
2276 | }; speed;}), | ||
2277 | udev->bus->controller->driver->name, | ||
2278 | udev->devnum); | ||
2279 | 2109 | ||
2280 | /* Set up TT records, if needed */ | 2110 | /* Set up TT records, if needed */ |
2281 | if (hdev->tt) { | 2111 | if (hdev->tt) { |
@@ -2317,6 +2147,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2317 | * down tremendously by NAKing the unexpectedly | 2147 | * down tremendously by NAKing the unexpectedly |
2318 | * early status stage. Also, retry on all errors; | 2148 | * early status stage. Also, retry on all errors; |
2319 | * some devices are flakey. | 2149 | * some devices are flakey. |
2150 | * 255 is for WUSB devices, we actually need to use 512. | ||
2151 | * WUSB1.0[4.8.1]. | ||
2320 | */ | 2152 | */ |
2321 | for (j = 0; j < 3; ++j) { | 2153 | for (j = 0; j < 3; ++j) { |
2322 | buf->bMaxPacketSize0 = 0; | 2154 | buf->bMaxPacketSize0 = 0; |
@@ -2326,7 +2158,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2326 | buf, GET_DESCRIPTOR_BUFSIZE, | 2158 | buf, GET_DESCRIPTOR_BUFSIZE, |
2327 | (i ? USB_CTRL_GET_TIMEOUT : 1000)); | 2159 | (i ? USB_CTRL_GET_TIMEOUT : 1000)); |
2328 | switch (buf->bMaxPacketSize0) { | 2160 | switch (buf->bMaxPacketSize0) { |
2329 | case 8: case 16: case 32: case 64: | 2161 | case 8: case 16: case 32: case 64: case 255: |
2330 | if (buf->bDescriptorType == | 2162 | if (buf->bDescriptorType == |
2331 | USB_DT_DEVICE) { | 2163 | USB_DT_DEVICE) { |
2332 | r = 0; | 2164 | r = 0; |
@@ -2400,7 +2232,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2400 | if (retval) | 2232 | if (retval) |
2401 | goto fail; | 2233 | goto fail; |
2402 | 2234 | ||
2403 | i = udev->descriptor.bMaxPacketSize0; | 2235 | i = udev->descriptor.bMaxPacketSize0 == 0xff? |
2236 | 512 : udev->descriptor.bMaxPacketSize0; | ||
2404 | if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { | 2237 | if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { |
2405 | if (udev->speed != USB_SPEED_FULL || | 2238 | if (udev->speed != USB_SPEED_FULL || |
2406 | !(i == 8 || i == 16 || i == 32 || i == 64)) { | 2239 | !(i == 8 || i == 16 || i == 32 || i == 64)) { |
@@ -2585,6 +2418,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
2585 | usb_set_device_state(udev, USB_STATE_POWERED); | 2418 | usb_set_device_state(udev, USB_STATE_POWERED); |
2586 | udev->speed = USB_SPEED_UNKNOWN; | 2419 | udev->speed = USB_SPEED_UNKNOWN; |
2587 | udev->bus_mA = hub->mA_per_port; | 2420 | udev->bus_mA = hub->mA_per_port; |
2421 | udev->level = hdev->level + 1; | ||
2588 | 2422 | ||
2589 | /* set the address */ | 2423 | /* set the address */ |
2590 | choose_address(udev); | 2424 | choose_address(udev); |
@@ -2736,17 +2570,6 @@ static void hub_events(void) | |||
2736 | usb_get_intf(intf); | 2570 | usb_get_intf(intf); |
2737 | spin_unlock_irq(&hub_event_lock); | 2571 | spin_unlock_irq(&hub_event_lock); |
2738 | 2572 | ||
2739 | /* Is this is a root hub wanting to reactivate the downstream | ||
2740 | * ports? If so, be sure the interface resumes even if its | ||
2741 | * stub "device" node was never suspended. | ||
2742 | */ | ||
2743 | if (i) { | ||
2744 | dpm_runtime_resume(&hdev->dev); | ||
2745 | dpm_runtime_resume(&intf->dev); | ||
2746 | usb_put_intf(intf); | ||
2747 | continue; | ||
2748 | } | ||
2749 | |||
2750 | /* Lock the device, then check to see if we were | 2573 | /* Lock the device, then check to see if we were |
2751 | * disconnected while waiting for the lock to succeed. */ | 2574 | * disconnected while waiting for the lock to succeed. */ |
2752 | if (locktree(hdev) < 0) { | 2575 | if (locktree(hdev) < 0) { |
@@ -2763,6 +2586,13 @@ static void hub_events(void) | |||
2763 | goto loop; | 2586 | goto loop; |
2764 | } | 2587 | } |
2765 | 2588 | ||
2589 | /* Is this is a root hub wanting to reactivate the downstream | ||
2590 | * ports? If so, be sure the interface resumes even if its | ||
2591 | * stub "device" node was never suspended. | ||
2592 | */ | ||
2593 | if (i) | ||
2594 | usb_autoresume_device(hdev, 0); | ||
2595 | |||
2766 | /* If this is an inactive or suspended hub, do nothing */ | 2596 | /* If this is an inactive or suspended hub, do nothing */ |
2767 | if (hub->quiescing) | 2597 | if (hub->quiescing) |
2768 | goto loop; | 2598 | goto loop; |
@@ -2900,7 +2730,7 @@ static void hub_events(void) | |||
2900 | 2730 | ||
2901 | /* If this is a root hub, tell the HCD it's okay to | 2731 | /* If this is a root hub, tell the HCD it's okay to |
2902 | * re-enable port-change interrupts now. */ | 2732 | * re-enable port-change interrupts now. */ |
2903 | if (!hdev->parent) | 2733 | if (!hdev->parent && !hub->busy_bits[0]) |
2904 | usb_enable_root_hub_irq(hdev->bus); | 2734 | usb_enable_root_hub_irq(hdev->bus); |
2905 | 2735 | ||
2906 | loop: | 2736 | loop: |
@@ -3075,6 +2905,9 @@ int usb_reset_device(struct usb_device *udev) | |||
3075 | break; | 2905 | break; |
3076 | } | 2906 | } |
3077 | clear_bit(port1, parent_hub->busy_bits); | 2907 | clear_bit(port1, parent_hub->busy_bits); |
2908 | if (!parent_hdev->parent && !parent_hub->busy_bits[0]) | ||
2909 | usb_enable_root_hub_irq(parent_hdev->bus); | ||
2910 | |||
3078 | if (ret < 0) | 2911 | if (ret < 0) |
3079 | goto re_enumerate; | 2912 | goto re_enumerate; |
3080 | 2913 | ||
@@ -3128,6 +2961,7 @@ re_enumerate: | |||
3128 | hub_port_logical_disconnect(parent_hub, port1); | 2961 | hub_port_logical_disconnect(parent_hub, port1); |
3129 | return -ENODEV; | 2962 | return -ENODEV; |
3130 | } | 2963 | } |
2964 | EXPORT_SYMBOL(usb_reset_device); | ||
3131 | 2965 | ||
3132 | /** | 2966 | /** |
3133 | * usb_reset_composite_device - warn interface drivers and perform a USB port reset | 2967 | * usb_reset_composite_device - warn interface drivers and perform a USB port reset |
@@ -3163,6 +2997,9 @@ int usb_reset_composite_device(struct usb_device *udev, | |||
3163 | return -EINVAL; | 2997 | return -EINVAL; |
3164 | } | 2998 | } |
3165 | 2999 | ||
3000 | /* Prevent autosuspend during the reset */ | ||
3001 | usb_autoresume_device(udev, 1); | ||
3002 | |||
3166 | if (iface && iface->condition != USB_INTERFACE_BINDING) | 3003 | if (iface && iface->condition != USB_INTERFACE_BINDING) |
3167 | iface = NULL; | 3004 | iface = NULL; |
3168 | 3005 | ||
@@ -3204,5 +3041,7 @@ int usb_reset_composite_device(struct usb_device *udev, | |||
3204 | } | 3041 | } |
3205 | } | 3042 | } |
3206 | 3043 | ||
3044 | usb_autosuspend_device(udev, 1); | ||
3207 | return ret; | 3045 | return ret; |
3208 | } | 3046 | } |
3047 | EXPORT_SYMBOL(usb_reset_composite_device); | ||
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 29d5f45a8456..0f8e82a4d480 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -212,7 +212,8 @@ struct usb_hub { | |||
212 | unsigned long event_bits[1]; /* status change bitmask */ | 212 | unsigned long event_bits[1]; /* status change bitmask */ |
213 | unsigned long change_bits[1]; /* ports with logical connect | 213 | unsigned long change_bits[1]; /* ports with logical connect |
214 | status change */ | 214 | status change */ |
215 | unsigned long busy_bits[1]; /* ports being reset */ | 215 | unsigned long busy_bits[1]; /* ports being reset or |
216 | resumed */ | ||
216 | #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ | 217 | #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ |
217 | #error event_bits[] is too short! | 218 | #error event_bits[] is too short! |
218 | #endif | 219 | #endif |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 3182c2224ba2..df3d152f0493 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "hcd.h" | 44 | #include "hcd.h" |
45 | 45 | ||
46 | static struct super_operations usbfs_ops; | 46 | static struct super_operations usbfs_ops; |
47 | static struct file_operations default_file_operations; | 47 | static const struct file_operations default_file_operations; |
48 | static struct vfsmount *usbfs_mount; | 48 | static struct vfsmount *usbfs_mount; |
49 | static int usbfs_mount_count; /* = 0 */ | 49 | static int usbfs_mount_count; /* = 0 */ |
50 | static int ignore_mount = 0; | 50 | static int ignore_mount = 0; |
@@ -249,7 +249,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de | |||
249 | inode->i_mode = mode; | 249 | inode->i_mode = mode; |
250 | inode->i_uid = current->fsuid; | 250 | inode->i_uid = current->fsuid; |
251 | inode->i_gid = current->fsgid; | 251 | inode->i_gid = current->fsgid; |
252 | inode->i_blksize = PAGE_CACHE_SIZE; | ||
253 | inode->i_blocks = 0; | 252 | inode->i_blocks = 0; |
254 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 253 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
255 | switch (mode & S_IFMT) { | 254 | switch (mode & S_IFMT) { |
@@ -402,13 +401,13 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) | |||
402 | 401 | ||
403 | static int default_open (struct inode *inode, struct file *file) | 402 | static int default_open (struct inode *inode, struct file *file) |
404 | { | 403 | { |
405 | if (inode->u.generic_ip) | 404 | if (inode->i_private) |
406 | file->private_data = inode->u.generic_ip; | 405 | file->private_data = inode->i_private; |
407 | 406 | ||
408 | return 0; | 407 | return 0; |
409 | } | 408 | } |
410 | 409 | ||
411 | static struct file_operations default_file_operations = { | 410 | static const struct file_operations default_file_operations = { |
412 | .read = default_read_file, | 411 | .read = default_read_file, |
413 | .write = default_write_file, | 412 | .write = default_write_file, |
414 | .open = default_open, | 413 | .open = default_open, |
@@ -495,7 +494,7 @@ static int fs_create_by_name (const char *name, mode_t mode, | |||
495 | 494 | ||
496 | static struct dentry *fs_create_file (const char *name, mode_t mode, | 495 | static struct dentry *fs_create_file (const char *name, mode_t mode, |
497 | struct dentry *parent, void *data, | 496 | struct dentry *parent, void *data, |
498 | struct file_operations *fops, | 497 | const struct file_operations *fops, |
499 | uid_t uid, gid_t gid) | 498 | uid_t uid, gid_t gid) |
500 | { | 499 | { |
501 | struct dentry *dentry; | 500 | struct dentry *dentry; |
@@ -509,7 +508,7 @@ static struct dentry *fs_create_file (const char *name, mode_t mode, | |||
509 | } else { | 508 | } else { |
510 | if (dentry->d_inode) { | 509 | if (dentry->d_inode) { |
511 | if (data) | 510 | if (data) |
512 | dentry->d_inode->u.generic_ip = data; | 511 | dentry->d_inode->i_private = data; |
513 | if (fops) | 512 | if (fops) |
514 | dentry->d_inode->i_fop = fops; | 513 | dentry->d_inode->i_fop = fops; |
515 | dentry->d_inode->i_uid = uid; | 514 | dentry->d_inode->i_uid = uid; |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 4cc8d3e67db7..85b1cd18336f 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -23,59 +23,44 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs) | |||
23 | } | 23 | } |
24 | 24 | ||
25 | 25 | ||
26 | static void timeout_kill(unsigned long data) | 26 | /* |
27 | { | 27 | * Starts urb and waits for completion or timeout. Note that this call |
28 | struct urb *urb = (struct urb *) data; | 28 | * is NOT interruptible. Many device driver i/o requests should be |
29 | 29 | * interruptible and therefore these drivers should implement their | |
30 | usb_unlink_urb(urb); | 30 | * own interruptible routines. |
31 | } | 31 | */ |
32 | 32 | static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) | |
33 | // Starts urb and waits for completion or timeout | ||
34 | // note that this call is NOT interruptible, while | ||
35 | // many device driver i/o requests should be interruptible | ||
36 | static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) | ||
37 | { | 33 | { |
38 | struct completion done; | 34 | struct completion done; |
39 | struct timer_list timer; | 35 | unsigned long expire; |
40 | int status; | 36 | int status; |
41 | 37 | ||
42 | init_completion(&done); | 38 | init_completion(&done); |
43 | urb->context = &done; | 39 | urb->context = &done; |
44 | urb->actual_length = 0; | 40 | urb->actual_length = 0; |
45 | status = usb_submit_urb(urb, GFP_NOIO); | 41 | status = usb_submit_urb(urb, GFP_NOIO); |
46 | 42 | if (unlikely(status)) | |
47 | if (status == 0) { | 43 | goto out; |
48 | if (timeout > 0) { | 44 | |
49 | init_timer(&timer); | 45 | expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; |
50 | timer.expires = jiffies + msecs_to_jiffies(timeout); | 46 | if (!wait_for_completion_timeout(&done, expire)) { |
51 | timer.data = (unsigned long)urb; | 47 | |
52 | timer.function = timeout_kill; | 48 | dev_dbg(&urb->dev->dev, |
53 | /* grr. timeout _should_ include submit delays. */ | 49 | "%s timed out on ep%d%s len=%d/%d\n", |
54 | add_timer(&timer); | 50 | current->comm, |
55 | } | 51 | usb_pipeendpoint(urb->pipe), |
56 | wait_for_completion(&done); | 52 | usb_pipein(urb->pipe) ? "in" : "out", |
53 | urb->actual_length, | ||
54 | urb->transfer_buffer_length); | ||
55 | |||
56 | usb_kill_urb(urb); | ||
57 | status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status; | ||
58 | } else | ||
57 | status = urb->status; | 59 | status = urb->status; |
58 | /* note: HCDs return ETIMEDOUT for other reasons too */ | 60 | out: |
59 | if (status == -ECONNRESET) { | ||
60 | dev_dbg(&urb->dev->dev, | ||
61 | "%s timed out on ep%d%s len=%d/%d\n", | ||
62 | current->comm, | ||
63 | usb_pipeendpoint(urb->pipe), | ||
64 | usb_pipein(urb->pipe) ? "in" : "out", | ||
65 | urb->actual_length, | ||
66 | urb->transfer_buffer_length | ||
67 | ); | ||
68 | if (urb->actual_length > 0) | ||
69 | status = 0; | ||
70 | else | ||
71 | status = -ETIMEDOUT; | ||
72 | } | ||
73 | if (timeout > 0) | ||
74 | del_timer_sync(&timer); | ||
75 | } | ||
76 | |||
77 | if (actual_length) | 61 | if (actual_length) |
78 | *actual_length = urb->actual_length; | 62 | *actual_length = urb->actual_length; |
63 | |||
79 | usb_free_urb(urb); | 64 | usb_free_urb(urb); |
80 | return status; | 65 | return status; |
81 | } | 66 | } |
@@ -263,7 +248,7 @@ static void sg_clean (struct usb_sg_request *io) | |||
263 | 248 | ||
264 | static void sg_complete (struct urb *urb, struct pt_regs *regs) | 249 | static void sg_complete (struct urb *urb, struct pt_regs *regs) |
265 | { | 250 | { |
266 | struct usb_sg_request *io = (struct usb_sg_request *) urb->context; | 251 | struct usb_sg_request *io = urb->context; |
267 | 252 | ||
268 | spin_lock (&io->lock); | 253 | spin_lock (&io->lock); |
269 | 254 | ||
@@ -999,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
999 | ep = dev->ep_in[epnum]; | 984 | ep = dev->ep_in[epnum]; |
1000 | dev->ep_in[epnum] = NULL; | 985 | dev->ep_in[epnum] = NULL; |
1001 | } | 986 | } |
1002 | if (ep && dev->bus && dev->bus->op && dev->bus->op->disable) | 987 | if (ep && dev->bus) |
1003 | dev->bus->op->disable(dev, ep); | 988 | usb_hcd_endpoint_disable(dev, ep); |
1004 | } | 989 | } |
1005 | 990 | ||
1006 | /** | 991 | /** |
@@ -1381,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) | |||
1381 | if (cp && configuration == 0) | 1366 | if (cp && configuration == 0) |
1382 | dev_warn(&dev->dev, "config 0 descriptor??\n"); | 1367 | dev_warn(&dev->dev, "config 0 descriptor??\n"); |
1383 | 1368 | ||
1384 | if (dev->state == USB_STATE_SUSPENDED) | ||
1385 | return -EHOSTUNREACH; | ||
1386 | |||
1387 | /* Allocate memory for new interfaces before doing anything else, | 1369 | /* Allocate memory for new interfaces before doing anything else, |
1388 | * so that if we run out then nothing will have changed. */ | 1370 | * so that if we run out then nothing will have changed. */ |
1389 | n = nintf = 0; | 1371 | n = nintf = 0; |
@@ -1418,6 +1400,11 @@ free_interfaces: | |||
1418 | configuration, -i); | 1400 | configuration, -i); |
1419 | } | 1401 | } |
1420 | 1402 | ||
1403 | /* Wake up the device so we can send it the Set-Config request */ | ||
1404 | ret = usb_autoresume_device(dev, 1); | ||
1405 | if (ret) | ||
1406 | goto free_interfaces; | ||
1407 | |||
1421 | /* if it's already configured, clear out old state first. | 1408 | /* if it's already configured, clear out old state first. |
1422 | * getting rid of old interfaces means unbinding their drivers. | 1409 | * getting rid of old interfaces means unbinding their drivers. |
1423 | */ | 1410 | */ |
@@ -1437,6 +1424,7 @@ free_interfaces: | |||
1437 | dev->actconfig = cp; | 1424 | dev->actconfig = cp; |
1438 | if (!cp) { | 1425 | if (!cp) { |
1439 | usb_set_device_state(dev, USB_STATE_ADDRESS); | 1426 | usb_set_device_state(dev, USB_STATE_ADDRESS); |
1427 | usb_autosuspend_device(dev, 1); | ||
1440 | goto free_interfaces; | 1428 | goto free_interfaces; |
1441 | } | 1429 | } |
1442 | usb_set_device_state(dev, USB_STATE_CONFIGURED); | 1430 | usb_set_device_state(dev, USB_STATE_CONFIGURED); |
@@ -1505,8 +1493,68 @@ free_interfaces: | |||
1505 | usb_create_sysfs_intf_files (intf); | 1493 | usb_create_sysfs_intf_files (intf); |
1506 | } | 1494 | } |
1507 | 1495 | ||
1496 | usb_autosuspend_device(dev, 1); | ||
1497 | return 0; | ||
1498 | } | ||
1499 | |||
1500 | struct set_config_request { | ||
1501 | struct usb_device *udev; | ||
1502 | int config; | ||
1503 | struct work_struct work; | ||
1504 | }; | ||
1505 | |||
1506 | /* Worker routine for usb_driver_set_configuration() */ | ||
1507 | static void driver_set_config_work(void *_req) | ||
1508 | { | ||
1509 | struct set_config_request *req = _req; | ||
1510 | |||
1511 | usb_lock_device(req->udev); | ||
1512 | usb_set_configuration(req->udev, req->config); | ||
1513 | usb_unlock_device(req->udev); | ||
1514 | usb_put_dev(req->udev); | ||
1515 | kfree(req); | ||
1516 | } | ||
1517 | |||
1518 | /** | ||
1519 | * usb_driver_set_configuration - Provide a way for drivers to change device configurations | ||
1520 | * @udev: the device whose configuration is being updated | ||
1521 | * @config: the configuration being chosen. | ||
1522 | * Context: In process context, must be able to sleep | ||
1523 | * | ||
1524 | * Device interface drivers are not allowed to change device configurations. | ||
1525 | * This is because changing configurations will destroy the interface the | ||
1526 | * driver is bound to and create new ones; it would be like a floppy-disk | ||
1527 | * driver telling the computer to replace the floppy-disk drive with a | ||
1528 | * tape drive! | ||
1529 | * | ||
1530 | * Still, in certain specialized circumstances the need may arise. This | ||
1531 | * routine gets around the normal restrictions by using a work thread to | ||
1532 | * submit the change-config request. | ||
1533 | * | ||
1534 | * Returns 0 if the request was succesfully queued, error code otherwise. | ||
1535 | * The caller has no way to know whether the queued request will eventually | ||
1536 | * succeed. | ||
1537 | */ | ||
1538 | int usb_driver_set_configuration(struct usb_device *udev, int config) | ||
1539 | { | ||
1540 | struct set_config_request *req; | ||
1541 | |||
1542 | req = kmalloc(sizeof(*req), GFP_KERNEL); | ||
1543 | if (!req) | ||
1544 | return -ENOMEM; | ||
1545 | req->udev = udev; | ||
1546 | req->config = config; | ||
1547 | INIT_WORK(&req->work, driver_set_config_work, req); | ||
1548 | |||
1549 | usb_get_dev(udev); | ||
1550 | if (!schedule_work(&req->work)) { | ||
1551 | usb_put_dev(udev); | ||
1552 | kfree(req); | ||
1553 | return -EINVAL; | ||
1554 | } | ||
1508 | return 0; | 1555 | return 0; |
1509 | } | 1556 | } |
1557 | EXPORT_SYMBOL_GPL(usb_driver_set_configuration); | ||
1510 | 1558 | ||
1511 | // synchronous request completion model | 1559 | // synchronous request completion model |
1512 | EXPORT_SYMBOL(usb_control_msg); | 1560 | EXPORT_SYMBOL(usb_control_msg); |
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index b042676af0a5..6b36897ca151 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c | |||
@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev) | |||
50 | 50 | ||
51 | void usb_notify_remove_device(struct usb_device *udev) | 51 | void usb_notify_remove_device(struct usb_device *udev) |
52 | { | 52 | { |
53 | /* Protect against simultaneous usbfs open */ | ||
54 | mutex_lock(&usbfs_mutex); | ||
53 | blocking_notifier_call_chain(&usb_notifier_list, | 55 | blocking_notifier_call_chain(&usb_notifier_list, |
54 | USB_DEVICE_REMOVE, udev); | 56 | USB_DEVICE_REMOVE, udev); |
57 | mutex_unlock(&usbfs_mutex); | ||
55 | } | 58 | } |
56 | 59 | ||
57 | void usb_notify_add_bus(struct usb_bus *ubus) | 60 | void usb_notify_add_bus(struct usb_bus *ubus) |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index dec973affb0f..55d8f575206d 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -60,7 +60,7 @@ static ssize_t | |||
60 | set_bConfigurationValue (struct device *dev, struct device_attribute *attr, | 60 | set_bConfigurationValue (struct device *dev, struct device_attribute *attr, |
61 | const char *buf, size_t count) | 61 | const char *buf, size_t count) |
62 | { | 62 | { |
63 | struct usb_device *udev = udev = to_usb_device (dev); | 63 | struct usb_device *udev = to_usb_device (dev); |
64 | int config, value; | 64 | int config, value; |
65 | 65 | ||
66 | if (sscanf (buf, "%u", &config) != 1 || config > 255) | 66 | if (sscanf (buf, "%u", &config) != 1 || config > 255) |
@@ -186,6 +186,7 @@ usb_descriptor_attr (bMaxPacketSize0, "%d\n") | |||
186 | 186 | ||
187 | static struct attribute *dev_attrs[] = { | 187 | static struct attribute *dev_attrs[] = { |
188 | /* current configuration's attributes */ | 188 | /* current configuration's attributes */ |
189 | &dev_attr_configuration.attr, | ||
189 | &dev_attr_bNumInterfaces.attr, | 190 | &dev_attr_bNumInterfaces.attr, |
190 | &dev_attr_bConfigurationValue.attr, | 191 | &dev_attr_bConfigurationValue.attr, |
191 | &dev_attr_bmAttributes.attr, | 192 | &dev_attr_bmAttributes.attr, |
@@ -209,20 +210,40 @@ static struct attribute_group dev_attr_grp = { | |||
209 | .attrs = dev_attrs, | 210 | .attrs = dev_attrs, |
210 | }; | 211 | }; |
211 | 212 | ||
212 | void usb_create_sysfs_dev_files (struct usb_device *udev) | 213 | int usb_create_sysfs_dev_files(struct usb_device *udev) |
213 | { | 214 | { |
214 | struct device *dev = &udev->dev; | 215 | struct device *dev = &udev->dev; |
216 | int retval; | ||
215 | 217 | ||
216 | sysfs_create_group(&dev->kobj, &dev_attr_grp); | 218 | retval = sysfs_create_group(&dev->kobj, &dev_attr_grp); |
219 | if (retval) | ||
220 | return retval; | ||
217 | 221 | ||
218 | if (udev->manufacturer) | 222 | if (udev->manufacturer) { |
219 | device_create_file (dev, &dev_attr_manufacturer); | 223 | retval = device_create_file (dev, &dev_attr_manufacturer); |
220 | if (udev->product) | 224 | if (retval) |
221 | device_create_file (dev, &dev_attr_product); | 225 | goto error; |
222 | if (udev->serial) | 226 | } |
223 | device_create_file (dev, &dev_attr_serial); | 227 | if (udev->product) { |
224 | device_create_file (dev, &dev_attr_configuration); | 228 | retval = device_create_file (dev, &dev_attr_product); |
225 | usb_create_ep_files(dev, &udev->ep0, udev); | 229 | if (retval) |
230 | goto error; | ||
231 | } | ||
232 | if (udev->serial) { | ||
233 | retval = device_create_file (dev, &dev_attr_serial); | ||
234 | if (retval) | ||
235 | goto error; | ||
236 | } | ||
237 | retval = usb_create_ep_files(dev, &udev->ep0, udev); | ||
238 | if (retval) | ||
239 | goto error; | ||
240 | return 0; | ||
241 | error: | ||
242 | usb_remove_ep_files(&udev->ep0); | ||
243 | device_remove_file(dev, &dev_attr_manufacturer); | ||
244 | device_remove_file(dev, &dev_attr_product); | ||
245 | device_remove_file(dev, &dev_attr_serial); | ||
246 | return retval; | ||
226 | } | 247 | } |
227 | 248 | ||
228 | void usb_remove_sysfs_dev_files (struct usb_device *udev) | 249 | void usb_remove_sysfs_dev_files (struct usb_device *udev) |
@@ -238,7 +259,6 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev) | |||
238 | device_remove_file(dev, &dev_attr_product); | 259 | device_remove_file(dev, &dev_attr_product); |
239 | if (udev->serial) | 260 | if (udev->serial) |
240 | device_remove_file(dev, &dev_attr_serial); | 261 | device_remove_file(dev, &dev_attr_serial); |
241 | device_remove_file (dev, &dev_attr_configuration); | ||
242 | } | 262 | } |
243 | 263 | ||
244 | /* Interface fields */ | 264 | /* Interface fields */ |
@@ -340,18 +360,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) | |||
340 | usb_remove_ep_files(&iface_desc->endpoint[i]); | 360 | usb_remove_ep_files(&iface_desc->endpoint[i]); |
341 | } | 361 | } |
342 | 362 | ||
343 | void usb_create_sysfs_intf_files (struct usb_interface *intf) | 363 | int usb_create_sysfs_intf_files(struct usb_interface *intf) |
344 | { | 364 | { |
345 | struct usb_device *udev = interface_to_usbdev(intf); | 365 | struct usb_device *udev = interface_to_usbdev(intf); |
346 | struct usb_host_interface *alt = intf->cur_altsetting; | 366 | struct usb_host_interface *alt = intf->cur_altsetting; |
367 | int retval; | ||
347 | 368 | ||
348 | sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); | 369 | retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); |
370 | if (retval) | ||
371 | goto error; | ||
349 | 372 | ||
350 | if (alt->string == NULL) | 373 | if (alt->string == NULL) |
351 | alt->string = usb_cache_string(udev, alt->desc.iInterface); | 374 | alt->string = usb_cache_string(udev, alt->desc.iInterface); |
352 | if (alt->string) | 375 | if (alt->string) |
353 | device_create_file(&intf->dev, &dev_attr_interface); | 376 | retval = device_create_file(&intf->dev, &dev_attr_interface); |
354 | usb_create_intf_ep_files(intf, udev); | 377 | usb_create_intf_ep_files(intf, udev); |
378 | return 0; | ||
379 | error: | ||
380 | if (alt->string) | ||
381 | device_remove_file(&intf->dev, &dev_attr_interface); | ||
382 | sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); | ||
383 | usb_remove_intf_ep_files(intf); | ||
384 | return retval; | ||
355 | } | 385 | } |
356 | 386 | ||
357 | void usb_remove_sysfs_intf_files (struct usb_interface *intf) | 387 | void usb_remove_sysfs_intf_files (struct usb_interface *intf) |
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 9864988377c7..9801d08edacf 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -57,7 +57,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) | |||
57 | { | 57 | { |
58 | struct urb *urb; | 58 | struct urb *urb; |
59 | 59 | ||
60 | urb = (struct urb *)kmalloc(sizeof(struct urb) + | 60 | urb = kmalloc(sizeof(struct urb) + |
61 | iso_packets * sizeof(struct usb_iso_packet_descriptor), | 61 | iso_packets * sizeof(struct usb_iso_packet_descriptor), |
62 | mem_flags); | 62 | mem_flags); |
63 | if (!urb) { | 63 | if (!urb) { |
@@ -221,7 +221,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
221 | { | 221 | { |
222 | int pipe, temp, max; | 222 | int pipe, temp, max; |
223 | struct usb_device *dev; | 223 | struct usb_device *dev; |
224 | struct usb_operations *op; | ||
225 | int is_out; | 224 | int is_out; |
226 | 225 | ||
227 | if (!urb || urb->hcpriv || !urb->complete) | 226 | if (!urb || urb->hcpriv || !urb->complete) |
@@ -233,8 +232,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
233 | if (dev->bus->controller->power.power_state.event != PM_EVENT_ON | 232 | if (dev->bus->controller->power.power_state.event != PM_EVENT_ON |
234 | || dev->state == USB_STATE_SUSPENDED) | 233 | || dev->state == USB_STATE_SUSPENDED) |
235 | return -EHOSTUNREACH; | 234 | return -EHOSTUNREACH; |
236 | if (!(op = dev->bus->op) || !op->submit_urb) | ||
237 | return -ENODEV; | ||
238 | 235 | ||
239 | urb->status = -EINPROGRESS; | 236 | urb->status = -EINPROGRESS; |
240 | urb->actual_length = 0; | 237 | urb->actual_length = 0; |
@@ -376,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
376 | urb->interval = temp; | 373 | urb->interval = temp; |
377 | } | 374 | } |
378 | 375 | ||
379 | return op->submit_urb (urb, mem_flags); | 376 | return usb_hcd_submit_urb (urb, mem_flags); |
380 | } | 377 | } |
381 | 378 | ||
382 | /*-------------------------------------------------------------------*/ | 379 | /*-------------------------------------------------------------------*/ |
@@ -440,9 +437,9 @@ int usb_unlink_urb(struct urb *urb) | |||
440 | { | 437 | { |
441 | if (!urb) | 438 | if (!urb) |
442 | return -EINVAL; | 439 | return -EINVAL; |
443 | if (!(urb->dev && urb->dev->bus && urb->dev->bus->op)) | 440 | if (!(urb->dev && urb->dev->bus)) |
444 | return -ENODEV; | 441 | return -ENODEV; |
445 | return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET); | 442 | return usb_hcd_unlink_urb(urb, -ECONNRESET); |
446 | } | 443 | } |
447 | 444 | ||
448 | /** | 445 | /** |
@@ -468,13 +465,13 @@ int usb_unlink_urb(struct urb *urb) | |||
468 | void usb_kill_urb(struct urb *urb) | 465 | void usb_kill_urb(struct urb *urb) |
469 | { | 466 | { |
470 | might_sleep(); | 467 | might_sleep(); |
471 | if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op)) | 468 | if (!(urb && urb->dev && urb->dev->bus)) |
472 | return; | 469 | return; |
473 | spin_lock_irq(&urb->lock); | 470 | spin_lock_irq(&urb->lock); |
474 | ++urb->reject; | 471 | ++urb->reject; |
475 | spin_unlock_irq(&urb->lock); | 472 | spin_unlock_irq(&urb->lock); |
476 | 473 | ||
477 | urb->dev->bus->op->unlink_urb(urb, -ENOENT); | 474 | usb_hcd_unlink_urb(urb, -ENOENT); |
478 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); | 475 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); |
479 | 476 | ||
480 | spin_lock_irq(&urb->lock); | 477 | spin_lock_irq(&urb->lock); |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 184c24660a4c..60ef4ef0101a 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -67,7 +67,8 @@ static int nousb; /* Disable USB when built into kernel image */ | |||
67 | * Don't call this function unless you are bound to one of the interfaces | 67 | * Don't call this function unless you are bound to one of the interfaces |
68 | * on this device or you have locked the device! | 68 | * on this device or you have locked the device! |
69 | */ | 69 | */ |
70 | struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) | 70 | struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, |
71 | unsigned ifnum) | ||
71 | { | 72 | { |
72 | struct usb_host_config *config = dev->actconfig; | 73 | struct usb_host_config *config = dev->actconfig; |
73 | int i; | 74 | int i; |
@@ -100,8 +101,8 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) | |||
100 | * Don't call this function unless you are bound to the intf interface | 101 | * Don't call this function unless you are bound to the intf interface |
101 | * or you have locked the device! | 102 | * or you have locked the device! |
102 | */ | 103 | */ |
103 | struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, | 104 | struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf, |
104 | unsigned int altnum) | 105 | unsigned int altnum) |
105 | { | 106 | { |
106 | int i; | 107 | int i; |
107 | 108 | ||
@@ -112,87 +113,6 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, | |||
112 | return NULL; | 113 | return NULL; |
113 | } | 114 | } |
114 | 115 | ||
115 | /** | ||
116 | * usb_driver_claim_interface - bind a driver to an interface | ||
117 | * @driver: the driver to be bound | ||
118 | * @iface: the interface to which it will be bound; must be in the | ||
119 | * usb device's active configuration | ||
120 | * @priv: driver data associated with that interface | ||
121 | * | ||
122 | * This is used by usb device drivers that need to claim more than one | ||
123 | * interface on a device when probing (audio and acm are current examples). | ||
124 | * No device driver should directly modify internal usb_interface or | ||
125 | * usb_device structure members. | ||
126 | * | ||
127 | * Few drivers should need to use this routine, since the most natural | ||
128 | * way to bind to an interface is to return the private data from | ||
129 | * the driver's probe() method. | ||
130 | * | ||
131 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
132 | * writelock. So driver probe() entries don't need extra locking, | ||
133 | * but other call contexts may need to explicitly claim those locks. | ||
134 | */ | ||
135 | int usb_driver_claim_interface(struct usb_driver *driver, | ||
136 | struct usb_interface *iface, void* priv) | ||
137 | { | ||
138 | struct device *dev = &iface->dev; | ||
139 | |||
140 | if (dev->driver) | ||
141 | return -EBUSY; | ||
142 | |||
143 | dev->driver = &driver->driver; | ||
144 | usb_set_intfdata(iface, priv); | ||
145 | iface->condition = USB_INTERFACE_BOUND; | ||
146 | mark_active(iface); | ||
147 | |||
148 | /* if interface was already added, bind now; else let | ||
149 | * the future device_add() bind it, bypassing probe() | ||
150 | */ | ||
151 | if (device_is_registered(dev)) | ||
152 | device_bind_driver(dev); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * usb_driver_release_interface - unbind a driver from an interface | ||
159 | * @driver: the driver to be unbound | ||
160 | * @iface: the interface from which it will be unbound | ||
161 | * | ||
162 | * This can be used by drivers to release an interface without waiting | ||
163 | * for their disconnect() methods to be called. In typical cases this | ||
164 | * also causes the driver disconnect() method to be called. | ||
165 | * | ||
166 | * This call is synchronous, and may not be used in an interrupt context. | ||
167 | * Callers must own the device lock and the driver model's usb_bus_type.subsys | ||
168 | * writelock. So driver disconnect() entries don't need extra locking, | ||
169 | * but other call contexts may need to explicitly claim those locks. | ||
170 | */ | ||
171 | void usb_driver_release_interface(struct usb_driver *driver, | ||
172 | struct usb_interface *iface) | ||
173 | { | ||
174 | struct device *dev = &iface->dev; | ||
175 | |||
176 | /* this should never happen, don't release something that's not ours */ | ||
177 | if (!dev->driver || dev->driver != &driver->driver) | ||
178 | return; | ||
179 | |||
180 | /* don't release from within disconnect() */ | ||
181 | if (iface->condition != USB_INTERFACE_BOUND) | ||
182 | return; | ||
183 | |||
184 | /* don't release if the interface hasn't been added yet */ | ||
185 | if (device_is_registered(dev)) { | ||
186 | iface->condition = USB_INTERFACE_UNBINDING; | ||
187 | device_release_driver(dev); | ||
188 | } | ||
189 | |||
190 | dev->driver = NULL; | ||
191 | usb_set_intfdata(iface, NULL); | ||
192 | iface->condition = USB_INTERFACE_UNBOUND; | ||
193 | mark_quiesced(iface); | ||
194 | } | ||
195 | |||
196 | struct find_interface_arg { | 116 | struct find_interface_arg { |
197 | int minor; | 117 | int minor; |
198 | struct usb_interface *interface; | 118 | struct usb_interface *interface; |
@@ -204,7 +124,7 @@ static int __find_interface(struct device * dev, void * data) | |||
204 | struct usb_interface *intf; | 124 | struct usb_interface *intf; |
205 | 125 | ||
206 | /* can't look at usb devices, only interfaces */ | 126 | /* can't look at usb devices, only interfaces */ |
207 | if (dev->driver == &usb_generic_driver) | 127 | if (is_usb_device(dev)) |
208 | return 0; | 128 | return 0; |
209 | 129 | ||
210 | intf = to_usb_interface(dev); | 130 | intf = to_usb_interface(dev); |
@@ -227,127 +147,16 @@ static int __find_interface(struct device * dev, void * data) | |||
227 | struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) | 147 | struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) |
228 | { | 148 | { |
229 | struct find_interface_arg argb; | 149 | struct find_interface_arg argb; |
150 | int retval; | ||
230 | 151 | ||
231 | argb.minor = minor; | 152 | argb.minor = minor; |
232 | argb.interface = NULL; | 153 | argb.interface = NULL; |
233 | driver_for_each_device(&drv->driver, NULL, &argb, __find_interface); | 154 | /* eat the error, it will be in argb.interface */ |
155 | retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, | ||
156 | __find_interface); | ||
234 | return argb.interface; | 157 | return argb.interface; |
235 | } | 158 | } |
236 | 159 | ||
237 | #ifdef CONFIG_HOTPLUG | ||
238 | |||
239 | /* | ||
240 | * This sends an uevent to userspace, typically helping to load driver | ||
241 | * or other modules, configure the device, and more. Drivers can provide | ||
242 | * a MODULE_DEVICE_TABLE to help with module loading subtasks. | ||
243 | * | ||
244 | * We're called either from khubd (the typical case) or from root hub | ||
245 | * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle | ||
246 | * delays in event delivery. Use sysfs (and DEVPATH) to make sure the | ||
247 | * device (and this configuration!) are still present. | ||
248 | */ | ||
249 | static int usb_uevent(struct device *dev, char **envp, int num_envp, | ||
250 | char *buffer, int buffer_size) | ||
251 | { | ||
252 | struct usb_interface *intf; | ||
253 | struct usb_device *usb_dev; | ||
254 | struct usb_host_interface *alt; | ||
255 | int i = 0; | ||
256 | int length = 0; | ||
257 | |||
258 | if (!dev) | ||
259 | return -ENODEV; | ||
260 | |||
261 | /* driver is often null here; dev_dbg() would oops */ | ||
262 | pr_debug ("usb %s: uevent\n", dev->bus_id); | ||
263 | |||
264 | /* Must check driver_data here, as on remove driver is always NULL */ | ||
265 | if ((dev->driver == &usb_generic_driver) || | ||
266 | (dev->driver_data == &usb_generic_driver_data)) | ||
267 | return 0; | ||
268 | |||
269 | intf = to_usb_interface(dev); | ||
270 | usb_dev = interface_to_usbdev (intf); | ||
271 | alt = intf->cur_altsetting; | ||
272 | |||
273 | if (usb_dev->devnum < 0) { | ||
274 | pr_debug ("usb %s: already deleted?\n", dev->bus_id); | ||
275 | return -ENODEV; | ||
276 | } | ||
277 | if (!usb_dev->bus) { | ||
278 | pr_debug ("usb %s: bus removed?\n", dev->bus_id); | ||
279 | return -ENODEV; | ||
280 | } | ||
281 | |||
282 | #ifdef CONFIG_USB_DEVICEFS | ||
283 | /* If this is available, userspace programs can directly read | ||
284 | * all the device descriptors we don't tell them about. Or | ||
285 | * even act as usermode drivers. | ||
286 | * | ||
287 | * FIXME reduce hardwired intelligence here | ||
288 | */ | ||
289 | if (add_uevent_var(envp, num_envp, &i, | ||
290 | buffer, buffer_size, &length, | ||
291 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
292 | usb_dev->bus->busnum, usb_dev->devnum)) | ||
293 | return -ENOMEM; | ||
294 | #endif | ||
295 | |||
296 | /* per-device configurations are common */ | ||
297 | if (add_uevent_var(envp, num_envp, &i, | ||
298 | buffer, buffer_size, &length, | ||
299 | "PRODUCT=%x/%x/%x", | ||
300 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
301 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
302 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | ||
303 | return -ENOMEM; | ||
304 | |||
305 | /* class-based driver binding models */ | ||
306 | if (add_uevent_var(envp, num_envp, &i, | ||
307 | buffer, buffer_size, &length, | ||
308 | "TYPE=%d/%d/%d", | ||
309 | usb_dev->descriptor.bDeviceClass, | ||
310 | usb_dev->descriptor.bDeviceSubClass, | ||
311 | usb_dev->descriptor.bDeviceProtocol)) | ||
312 | return -ENOMEM; | ||
313 | |||
314 | if (add_uevent_var(envp, num_envp, &i, | ||
315 | buffer, buffer_size, &length, | ||
316 | "INTERFACE=%d/%d/%d", | ||
317 | alt->desc.bInterfaceClass, | ||
318 | alt->desc.bInterfaceSubClass, | ||
319 | alt->desc.bInterfaceProtocol)) | ||
320 | return -ENOMEM; | ||
321 | |||
322 | if (add_uevent_var(envp, num_envp, &i, | ||
323 | buffer, buffer_size, &length, | ||
324 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | ||
325 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
326 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
327 | le16_to_cpu(usb_dev->descriptor.bcdDevice), | ||
328 | usb_dev->descriptor.bDeviceClass, | ||
329 | usb_dev->descriptor.bDeviceSubClass, | ||
330 | usb_dev->descriptor.bDeviceProtocol, | ||
331 | alt->desc.bInterfaceClass, | ||
332 | alt->desc.bInterfaceSubClass, | ||
333 | alt->desc.bInterfaceProtocol)) | ||
334 | return -ENOMEM; | ||
335 | |||
336 | envp[i] = NULL; | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | #else | ||
342 | |||
343 | static int usb_uevent(struct device *dev, char **envp, | ||
344 | int num_envp, char *buffer, int buffer_size) | ||
345 | { | ||
346 | return -ENODEV; | ||
347 | } | ||
348 | |||
349 | #endif /* CONFIG_HOTPLUG */ | ||
350 | |||
351 | /** | 160 | /** |
352 | * usb_release_dev - free a usb device structure when all users of it are finished. | 161 | * usb_release_dev - free a usb device structure when all users of it are finished. |
353 | * @dev: device that's been disconnected | 162 | * @dev: device that's been disconnected |
@@ -361,14 +170,33 @@ static void usb_release_dev(struct device *dev) | |||
361 | 170 | ||
362 | udev = to_usb_device(dev); | 171 | udev = to_usb_device(dev); |
363 | 172 | ||
173 | #ifdef CONFIG_PM | ||
174 | cancel_delayed_work(&udev->autosuspend); | ||
175 | flush_scheduled_work(); | ||
176 | #endif | ||
364 | usb_destroy_configuration(udev); | 177 | usb_destroy_configuration(udev); |
365 | usb_bus_put(udev->bus); | 178 | usb_put_hcd(bus_to_hcd(udev->bus)); |
366 | kfree(udev->product); | 179 | kfree(udev->product); |
367 | kfree(udev->manufacturer); | 180 | kfree(udev->manufacturer); |
368 | kfree(udev->serial); | 181 | kfree(udev->serial); |
369 | kfree(udev); | 182 | kfree(udev); |
370 | } | 183 | } |
371 | 184 | ||
185 | #ifdef CONFIG_PM | ||
186 | |||
187 | /* usb_autosuspend_work - callback routine to autosuspend a USB device */ | ||
188 | static void usb_autosuspend_work(void *_udev) | ||
189 | { | ||
190 | struct usb_device *udev = _udev; | ||
191 | |||
192 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
193 | udev->auto_pm = 1; | ||
194 | usb_suspend_both(udev, PMSG_SUSPEND); | ||
195 | mutex_unlock(&udev->pm_mutex); | ||
196 | } | ||
197 | |||
198 | #endif | ||
199 | |||
372 | /** | 200 | /** |
373 | * usb_alloc_dev - usb device constructor (usbcore-internal) | 201 | * usb_alloc_dev - usb device constructor (usbcore-internal) |
374 | * @parent: hub to which device is connected; null to allocate a root hub | 202 | * @parent: hub to which device is connected; null to allocate a root hub |
@@ -390,8 +218,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
390 | if (!dev) | 218 | if (!dev) |
391 | return NULL; | 219 | return NULL; |
392 | 220 | ||
393 | bus = usb_bus_get(bus); | 221 | if (!usb_get_hcd(bus_to_hcd(bus))) { |
394 | if (!bus) { | ||
395 | kfree(dev); | 222 | kfree(dev); |
396 | return NULL; | 223 | return NULL; |
397 | } | 224 | } |
@@ -399,11 +226,12 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
399 | device_initialize(&dev->dev); | 226 | device_initialize(&dev->dev); |
400 | dev->dev.bus = &usb_bus_type; | 227 | dev->dev.bus = &usb_bus_type; |
401 | dev->dev.dma_mask = bus->controller->dma_mask; | 228 | dev->dev.dma_mask = bus->controller->dma_mask; |
402 | dev->dev.driver_data = &usb_generic_driver_data; | ||
403 | dev->dev.driver = &usb_generic_driver; | ||
404 | dev->dev.release = usb_release_dev; | 229 | dev->dev.release = usb_release_dev; |
405 | dev->state = USB_STATE_ATTACHED; | 230 | dev->state = USB_STATE_ATTACHED; |
406 | 231 | ||
232 | /* This magic assignment distinguishes devices from interfaces */ | ||
233 | dev->dev.platform_data = &usb_generic_driver; | ||
234 | |||
407 | INIT_LIST_HEAD(&dev->ep0.urb_list); | 235 | INIT_LIST_HEAD(&dev->ep0.urb_list); |
408 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; | 236 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; |
409 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; | 237 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; |
@@ -444,6 +272,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
444 | dev->parent = parent; | 272 | dev->parent = parent; |
445 | INIT_LIST_HEAD(&dev->filelist); | 273 | INIT_LIST_HEAD(&dev->filelist); |
446 | 274 | ||
275 | #ifdef CONFIG_PM | ||
276 | mutex_init(&dev->pm_mutex); | ||
277 | INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev); | ||
278 | #endif | ||
447 | return dev; | 279 | return dev; |
448 | } | 280 | } |
449 | 281 | ||
@@ -549,7 +381,7 @@ void usb_put_intf(struct usb_interface *intf) | |||
549 | * case the driver already owns the device lock.) | 381 | * case the driver already owns the device lock.) |
550 | */ | 382 | */ |
551 | int usb_lock_device_for_reset(struct usb_device *udev, | 383 | int usb_lock_device_for_reset(struct usb_device *udev, |
552 | struct usb_interface *iface) | 384 | const struct usb_interface *iface) |
553 | { | 385 | { |
554 | unsigned long jiffies_expire = jiffies + HZ; | 386 | unsigned long jiffies_expire = jiffies + HZ; |
555 | 387 | ||
@@ -672,7 +504,139 @@ exit: | |||
672 | */ | 504 | */ |
673 | int usb_get_current_frame_number(struct usb_device *dev) | 505 | int usb_get_current_frame_number(struct usb_device *dev) |
674 | { | 506 | { |
675 | return dev->bus->op->get_frame_number (dev); | 507 | return usb_hcd_get_frame_number (dev); |
508 | } | ||
509 | |||
510 | /** | ||
511 | * usb_endpoint_dir_in - check if the endpoint has IN direction | ||
512 | * @epd: endpoint to be checked | ||
513 | * | ||
514 | * Returns true if the endpoint is of type IN, otherwise it returns false. | ||
515 | */ | ||
516 | int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) | ||
517 | { | ||
518 | return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); | ||
519 | } | ||
520 | |||
521 | /** | ||
522 | * usb_endpoint_dir_out - check if the endpoint has OUT direction | ||
523 | * @epd: endpoint to be checked | ||
524 | * | ||
525 | * Returns true if the endpoint is of type OUT, otherwise it returns false. | ||
526 | */ | ||
527 | int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) | ||
528 | { | ||
529 | return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type | ||
534 | * @epd: endpoint to be checked | ||
535 | * | ||
536 | * Returns true if the endpoint is of type bulk, otherwise it returns false. | ||
537 | */ | ||
538 | int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd) | ||
539 | { | ||
540 | return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
541 | USB_ENDPOINT_XFER_BULK); | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type | ||
546 | * @epd: endpoint to be checked | ||
547 | * | ||
548 | * Returns true if the endpoint is of type interrupt, otherwise it returns | ||
549 | * false. | ||
550 | */ | ||
551 | int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) | ||
552 | { | ||
553 | return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
554 | USB_ENDPOINT_XFER_INT); | ||
555 | } | ||
556 | |||
557 | /** | ||
558 | * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type | ||
559 | * @epd: endpoint to be checked | ||
560 | * | ||
561 | * Returns true if the endpoint is of type isochronous, otherwise it returns | ||
562 | * false. | ||
563 | */ | ||
564 | int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd) | ||
565 | { | ||
566 | return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
567 | USB_ENDPOINT_XFER_ISOC); | ||
568 | } | ||
569 | |||
570 | /** | ||
571 | * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN | ||
572 | * @epd: endpoint to be checked | ||
573 | * | ||
574 | * Returns true if the endpoint has bulk transfer type and IN direction, | ||
575 | * otherwise it returns false. | ||
576 | */ | ||
577 | int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) | ||
578 | { | ||
579 | return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT | ||
584 | * @epd: endpoint to be checked | ||
585 | * | ||
586 | * Returns true if the endpoint has bulk transfer type and OUT direction, | ||
587 | * otherwise it returns false. | ||
588 | */ | ||
589 | int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) | ||
590 | { | ||
591 | return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); | ||
592 | } | ||
593 | |||
594 | /** | ||
595 | * usb_endpoint_is_int_in - check if the endpoint is interrupt IN | ||
596 | * @epd: endpoint to be checked | ||
597 | * | ||
598 | * Returns true if the endpoint has interrupt transfer type and IN direction, | ||
599 | * otherwise it returns false. | ||
600 | */ | ||
601 | int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) | ||
602 | { | ||
603 | return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); | ||
604 | } | ||
605 | |||
606 | /** | ||
607 | * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT | ||
608 | * @epd: endpoint to be checked | ||
609 | * | ||
610 | * Returns true if the endpoint has interrupt transfer type and OUT direction, | ||
611 | * otherwise it returns false. | ||
612 | */ | ||
613 | int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) | ||
614 | { | ||
615 | return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); | ||
616 | } | ||
617 | |||
618 | /** | ||
619 | * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN | ||
620 | * @epd: endpoint to be checked | ||
621 | * | ||
622 | * Returns true if the endpoint has isochronous transfer type and IN direction, | ||
623 | * otherwise it returns false. | ||
624 | */ | ||
625 | int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) | ||
626 | { | ||
627 | return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); | ||
628 | } | ||
629 | |||
630 | /** | ||
631 | * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT | ||
632 | * @epd: endpoint to be checked | ||
633 | * | ||
634 | * Returns true if the endpoint has isochronous transfer type and OUT direction, | ||
635 | * otherwise it returns false. | ||
636 | */ | ||
637 | int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) | ||
638 | { | ||
639 | return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); | ||
676 | } | 640 | } |
677 | 641 | ||
678 | /*-------------------------------------------------------------------*/ | 642 | /*-------------------------------------------------------------------*/ |
@@ -737,9 +701,9 @@ void *usb_buffer_alloc ( | |||
737 | dma_addr_t *dma | 701 | dma_addr_t *dma |
738 | ) | 702 | ) |
739 | { | 703 | { |
740 | if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc) | 704 | if (!dev || !dev->bus) |
741 | return NULL; | 705 | return NULL; |
742 | return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma); | 706 | return hcd_buffer_alloc (dev->bus, size, mem_flags, dma); |
743 | } | 707 | } |
744 | 708 | ||
745 | /** | 709 | /** |
@@ -760,9 +724,11 @@ void usb_buffer_free ( | |||
760 | dma_addr_t dma | 724 | dma_addr_t dma |
761 | ) | 725 | ) |
762 | { | 726 | { |
763 | if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free) | 727 | if (!dev || !dev->bus) |
764 | return; | 728 | return; |
765 | dev->bus->op->buffer_free (dev->bus, size, addr, dma); | 729 | if (!addr) |
730 | return; | ||
731 | hcd_buffer_free (dev->bus, size, addr, dma); | ||
766 | } | 732 | } |
767 | 733 | ||
768 | /** | 734 | /** |
@@ -911,8 +877,8 @@ void usb_buffer_unmap (struct urb *urb) | |||
911 | * | 877 | * |
912 | * Reverse the effect of this call with usb_buffer_unmap_sg(). | 878 | * Reverse the effect of this call with usb_buffer_unmap_sg(). |
913 | */ | 879 | */ |
914 | int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, | 880 | int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe, |
915 | struct scatterlist *sg, int nents) | 881 | struct scatterlist *sg, int nents) |
916 | { | 882 | { |
917 | struct usb_bus *bus; | 883 | struct usb_bus *bus; |
918 | struct device *controller; | 884 | struct device *controller; |
@@ -946,8 +912,8 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, | |||
946 | * Use this when you are re-using a scatterlist's data buffers for | 912 | * Use this when you are re-using a scatterlist's data buffers for |
947 | * another USB request. | 913 | * another USB request. |
948 | */ | 914 | */ |
949 | void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, | 915 | void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe, |
950 | struct scatterlist *sg, int n_hw_ents) | 916 | struct scatterlist *sg, int n_hw_ents) |
951 | { | 917 | { |
952 | struct usb_bus *bus; | 918 | struct usb_bus *bus; |
953 | struct device *controller; | 919 | struct device *controller; |
@@ -972,8 +938,8 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, | |||
972 | * | 938 | * |
973 | * Reverses the effect of usb_buffer_map_sg(). | 939 | * Reverses the effect of usb_buffer_map_sg(). |
974 | */ | 940 | */ |
975 | void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, | 941 | void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe, |
976 | struct scatterlist *sg, int n_hw_ents) | 942 | struct scatterlist *sg, int n_hw_ents) |
977 | { | 943 | { |
978 | struct usb_bus *bus; | 944 | struct usb_bus *bus; |
979 | struct device *controller; | 945 | struct device *controller; |
@@ -988,116 +954,6 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, | |||
988 | usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 954 | usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
989 | } | 955 | } |
990 | 956 | ||
991 | static int verify_suspended(struct device *dev, void *unused) | ||
992 | { | ||
993 | if (dev->driver == NULL) | ||
994 | return 0; | ||
995 | return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; | ||
996 | } | ||
997 | |||
998 | static int usb_generic_suspend(struct device *dev, pm_message_t message) | ||
999 | { | ||
1000 | struct usb_interface *intf; | ||
1001 | struct usb_driver *driver; | ||
1002 | int status; | ||
1003 | |||
1004 | /* USB devices enter SUSPEND state through their hubs, but can be | ||
1005 | * marked for FREEZE as soon as their children are already idled. | ||
1006 | * But those semantics are useless, so we equate the two (sigh). | ||
1007 | */ | ||
1008 | if (dev->driver == &usb_generic_driver) { | ||
1009 | if (dev->power.power_state.event == message.event) | ||
1010 | return 0; | ||
1011 | /* we need to rule out bogus requests through sysfs */ | ||
1012 | status = device_for_each_child(dev, NULL, verify_suspended); | ||
1013 | if (status) | ||
1014 | return status; | ||
1015 | return usb_suspend_device (to_usb_device(dev)); | ||
1016 | } | ||
1017 | |||
1018 | if ((dev->driver == NULL) || | ||
1019 | (dev->driver_data == &usb_generic_driver_data)) | ||
1020 | return 0; | ||
1021 | |||
1022 | intf = to_usb_interface(dev); | ||
1023 | driver = to_usb_driver(dev->driver); | ||
1024 | |||
1025 | /* with no hardware, USB interfaces only use FREEZE and ON states */ | ||
1026 | if (!is_active(intf)) | ||
1027 | return 0; | ||
1028 | |||
1029 | if (driver->suspend && driver->resume) { | ||
1030 | status = driver->suspend(intf, message); | ||
1031 | if (status) | ||
1032 | dev_err(dev, "%s error %d\n", "suspend", status); | ||
1033 | else | ||
1034 | mark_quiesced(intf); | ||
1035 | } else { | ||
1036 | // FIXME else if there's no suspend method, disconnect... | ||
1037 | dev_warn(dev, "no suspend for driver %s?\n", driver->name); | ||
1038 | mark_quiesced(intf); | ||
1039 | status = 0; | ||
1040 | } | ||
1041 | return status; | ||
1042 | } | ||
1043 | |||
1044 | static int usb_generic_resume(struct device *dev) | ||
1045 | { | ||
1046 | struct usb_interface *intf; | ||
1047 | struct usb_driver *driver; | ||
1048 | struct usb_device *udev; | ||
1049 | int status; | ||
1050 | |||
1051 | if (dev->power.power_state.event == PM_EVENT_ON) | ||
1052 | return 0; | ||
1053 | |||
1054 | /* mark things as "on" immediately, no matter what errors crop up */ | ||
1055 | dev->power.power_state.event = PM_EVENT_ON; | ||
1056 | |||
1057 | /* devices resume through their hubs */ | ||
1058 | if (dev->driver == &usb_generic_driver) { | ||
1059 | udev = to_usb_device(dev); | ||
1060 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1061 | return 0; | ||
1062 | return usb_resume_device (to_usb_device(dev)); | ||
1063 | } | ||
1064 | |||
1065 | if ((dev->driver == NULL) || | ||
1066 | (dev->driver_data == &usb_generic_driver_data)) { | ||
1067 | dev->power.power_state.event = PM_EVENT_FREEZE; | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | intf = to_usb_interface(dev); | ||
1072 | driver = to_usb_driver(dev->driver); | ||
1073 | |||
1074 | udev = interface_to_usbdev(intf); | ||
1075 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1076 | return 0; | ||
1077 | |||
1078 | /* if driver was suspended, it has a resume method; | ||
1079 | * however, sysfs can wrongly mark things as suspended | ||
1080 | * (on the "no suspend method" FIXME path above) | ||
1081 | */ | ||
1082 | if (driver->resume) { | ||
1083 | status = driver->resume(intf); | ||
1084 | if (status) { | ||
1085 | dev_err(dev, "%s error %d\n", "resume", status); | ||
1086 | mark_quiesced(intf); | ||
1087 | } | ||
1088 | } else | ||
1089 | dev_warn(dev, "no resume for driver %s?\n", driver->name); | ||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | struct bus_type usb_bus_type = { | ||
1094 | .name = "usb", | ||
1095 | .match = usb_device_match, | ||
1096 | .uevent = usb_uevent, | ||
1097 | .suspend = usb_generic_suspend, | ||
1098 | .resume = usb_generic_resume, | ||
1099 | }; | ||
1100 | |||
1101 | /* format to disable USB on kernel command line is: nousb */ | 957 | /* format to disable USB on kernel command line is: nousb */ |
1102 | __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); | 958 | __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); |
1103 | 959 | ||
@@ -1141,7 +997,7 @@ static int __init usb_init(void) | |||
1141 | retval = usb_hub_init(); | 997 | retval = usb_hub_init(); |
1142 | if (retval) | 998 | if (retval) |
1143 | goto hub_init_failed; | 999 | goto hub_init_failed; |
1144 | retval = driver_register(&usb_generic_driver); | 1000 | retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE); |
1145 | if (!retval) | 1001 | if (!retval) |
1146 | goto out; | 1002 | goto out; |
1147 | 1003 | ||
@@ -1171,7 +1027,7 @@ static void __exit usb_exit(void) | |||
1171 | if (nousb) | 1027 | if (nousb) |
1172 | return; | 1028 | return; |
1173 | 1029 | ||
1174 | driver_unregister(&usb_generic_driver); | 1030 | usb_deregister_device_driver(&usb_generic_driver); |
1175 | usb_major_cleanup(); | 1031 | usb_major_cleanup(); |
1176 | usbfs_cleanup(); | 1032 | usbfs_cleanup(); |
1177 | usb_deregister(&usbfs_driver); | 1033 | usb_deregister(&usbfs_driver); |
@@ -1201,20 +1057,27 @@ EXPORT_SYMBOL(usb_hub_tt_clear_buffer); | |||
1201 | 1057 | ||
1202 | EXPORT_SYMBOL(usb_lock_device_for_reset); | 1058 | EXPORT_SYMBOL(usb_lock_device_for_reset); |
1203 | 1059 | ||
1204 | EXPORT_SYMBOL(usb_driver_claim_interface); | ||
1205 | EXPORT_SYMBOL(usb_driver_release_interface); | ||
1206 | EXPORT_SYMBOL(usb_find_interface); | 1060 | EXPORT_SYMBOL(usb_find_interface); |
1207 | EXPORT_SYMBOL(usb_ifnum_to_if); | 1061 | EXPORT_SYMBOL(usb_ifnum_to_if); |
1208 | EXPORT_SYMBOL(usb_altnum_to_altsetting); | 1062 | EXPORT_SYMBOL(usb_altnum_to_altsetting); |
1209 | 1063 | ||
1210 | EXPORT_SYMBOL(usb_reset_device); | ||
1211 | EXPORT_SYMBOL(usb_reset_composite_device); | ||
1212 | |||
1213 | EXPORT_SYMBOL(__usb_get_extra_descriptor); | 1064 | EXPORT_SYMBOL(__usb_get_extra_descriptor); |
1214 | 1065 | ||
1215 | EXPORT_SYMBOL(usb_find_device); | 1066 | EXPORT_SYMBOL(usb_find_device); |
1216 | EXPORT_SYMBOL(usb_get_current_frame_number); | 1067 | EXPORT_SYMBOL(usb_get_current_frame_number); |
1217 | 1068 | ||
1069 | EXPORT_SYMBOL_GPL(usb_endpoint_dir_in); | ||
1070 | EXPORT_SYMBOL_GPL(usb_endpoint_dir_out); | ||
1071 | EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk); | ||
1072 | EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int); | ||
1073 | EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc); | ||
1074 | EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in); | ||
1075 | EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out); | ||
1076 | EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in); | ||
1077 | EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out); | ||
1078 | EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in); | ||
1079 | EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out); | ||
1080 | |||
1218 | EXPORT_SYMBOL (usb_buffer_alloc); | 1081 | EXPORT_SYMBOL (usb_buffer_alloc); |
1219 | EXPORT_SYMBOL (usb_buffer_free); | 1082 | EXPORT_SYMBOL (usb_buffer_free); |
1220 | 1083 | ||
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 49f69236b420..0c09ecced6e1 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -1,10 +1,10 @@ | |||
1 | /* Functions local to drivers/usb/core/ */ | 1 | /* Functions local to drivers/usb/core/ */ |
2 | 2 | ||
3 | extern void usb_create_sysfs_dev_files (struct usb_device *dev); | 3 | extern int usb_create_sysfs_dev_files (struct usb_device *dev); |
4 | extern void usb_remove_sysfs_dev_files (struct usb_device *dev); | 4 | extern void usb_remove_sysfs_dev_files (struct usb_device *dev); |
5 | extern void usb_create_sysfs_intf_files (struct usb_interface *intf); | 5 | extern int usb_create_sysfs_intf_files (struct usb_interface *intf); |
6 | extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); | 6 | extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); |
7 | extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint, | 7 | extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint, |
8 | struct usb_device *udev); | 8 | struct usb_device *udev); |
9 | extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); | 9 | extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); |
10 | 10 | ||
@@ -20,7 +20,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index); | |||
20 | extern int usb_set_configuration(struct usb_device *dev, int configuration); | 20 | extern int usb_set_configuration(struct usb_device *dev, int configuration); |
21 | 21 | ||
22 | extern void usb_kick_khubd(struct usb_device *dev); | 22 | extern void usb_kick_khubd(struct usb_device *dev); |
23 | extern void usb_suspend_root_hub(struct usb_device *hdev); | ||
24 | extern void usb_resume_root_hub(struct usb_device *dev); | 23 | extern void usb_resume_root_hub(struct usb_device *dev); |
25 | 24 | ||
26 | extern int usb_hub_init(void); | 25 | extern int usb_hub_init(void); |
@@ -30,28 +29,74 @@ extern void usb_major_cleanup(void); | |||
30 | extern int usb_host_init(void); | 29 | extern int usb_host_init(void); |
31 | extern void usb_host_cleanup(void); | 30 | extern void usb_host_cleanup(void); |
32 | 31 | ||
33 | extern int usb_suspend_device(struct usb_device *dev); | 32 | #ifdef CONFIG_PM |
34 | extern int usb_resume_device(struct usb_device *dev); | ||
35 | 33 | ||
36 | extern struct device_driver usb_generic_driver; | 34 | extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg); |
37 | extern int usb_generic_driver_data; | 35 | extern int usb_resume_both(struct usb_device *udev); |
38 | extern int usb_device_match(struct device *dev, struct device_driver *drv); | 36 | extern int usb_port_suspend(struct usb_device *dev); |
37 | extern int usb_port_resume(struct usb_device *dev); | ||
38 | |||
39 | #else | ||
40 | |||
41 | #define usb_suspend_both(udev, msg) 0 | ||
42 | static inline int usb_resume_both(struct usb_device *udev) | ||
43 | { | ||
44 | return 0; | ||
45 | } | ||
46 | #define usb_port_suspend(dev) 0 | ||
47 | #define usb_port_resume(dev) 0 | ||
48 | |||
49 | #endif | ||
50 | |||
51 | #ifdef CONFIG_USB_SUSPEND | ||
52 | |||
53 | #define USB_AUTOSUSPEND_DELAY (HZ*2) | ||
54 | |||
55 | extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt); | ||
56 | extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt); | ||
57 | |||
58 | #else | ||
59 | |||
60 | #define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0) | ||
61 | #define usb_autoresume_device(udev, inc_busy_cnt) 0 | ||
62 | |||
63 | #endif | ||
64 | |||
65 | extern struct bus_type usb_bus_type; | ||
66 | extern struct usb_device_driver usb_generic_driver; | ||
67 | |||
68 | /* Here's how we tell apart devices and interfaces. Luckily there's | ||
69 | * no such thing as a platform USB device, so we can steal the use | ||
70 | * of the platform_data field. */ | ||
71 | |||
72 | static inline int is_usb_device(const struct device *dev) | ||
73 | { | ||
74 | return dev->platform_data == &usb_generic_driver; | ||
75 | } | ||
76 | |||
77 | /* Do the same for device drivers and interface drivers. */ | ||
78 | |||
79 | static inline int is_usb_device_driver(struct device_driver *drv) | ||
80 | { | ||
81 | return container_of(drv, struct usbdrv_wrap, driver)-> | ||
82 | for_devices; | ||
83 | } | ||
39 | 84 | ||
40 | /* Interfaces and their "power state" are owned by usbcore */ | 85 | /* Interfaces and their "power state" are owned by usbcore */ |
41 | 86 | ||
42 | static inline void mark_active(struct usb_interface *f) | 87 | static inline void mark_active(struct usb_interface *f) |
43 | { | 88 | { |
44 | f->dev.power.power_state.event = PM_EVENT_ON; | 89 | f->is_active = 1; |
45 | } | 90 | } |
46 | 91 | ||
47 | static inline void mark_quiesced(struct usb_interface *f) | 92 | static inline void mark_quiesced(struct usb_interface *f) |
48 | { | 93 | { |
49 | f->dev.power.power_state.event = PM_EVENT_FREEZE; | 94 | f->is_active = 0; |
50 | } | 95 | } |
51 | 96 | ||
52 | static inline int is_active(struct usb_interface *f) | 97 | static inline int is_active(const struct usb_interface *f) |
53 | { | 98 | { |
54 | return f->dev.power.power_state.event == PM_EVENT_ON; | 99 | return f->is_active; |
55 | } | 100 | } |
56 | 101 | ||
57 | 102 | ||
@@ -59,9 +104,10 @@ static inline int is_active(struct usb_interface *f) | |||
59 | extern const char *usbcore_name; | 104 | extern const char *usbcore_name; |
60 | 105 | ||
61 | /* usbfs stuff */ | 106 | /* usbfs stuff */ |
107 | extern struct mutex usbfs_mutex; | ||
62 | extern struct usb_driver usbfs_driver; | 108 | extern struct usb_driver usbfs_driver; |
63 | extern struct file_operations usbfs_devices_fops; | 109 | extern const struct file_operations usbfs_devices_fops; |
64 | extern struct file_operations usbfs_device_file_operations; | 110 | extern const struct file_operations usbfs_device_file_operations; |
65 | extern void usbfs_conn_disc_event(void); | 111 | extern void usbfs_conn_disc_event(void); |
66 | 112 | ||
67 | extern int usbdev_init(void); | 113 | extern int usbdev_init(void); |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1a32d96774b4..8e5dd6f29d0b 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -26,7 +26,7 @@ config USB_GADGET | |||
26 | you need a low level bus controller driver, and some software | 26 | you need a low level bus controller driver, and some software |
27 | talking to it. Peripheral controllers are often discrete silicon, | 27 | talking to it. Peripheral controllers are often discrete silicon, |
28 | or are integrated with the CPU in a microcontroller. The more | 28 | or are integrated with the CPU in a microcontroller. The more |
29 | familiar host side controllers have names like like "EHCI", "OHCI", | 29 | familiar host side controllers have names like "EHCI", "OHCI", |
30 | or "UHCI", and are usually integrated into southbridges on PC | 30 | or "UHCI", and are usually integrated into southbridges on PC |
31 | motherboards. | 31 | motherboards. |
32 | 32 | ||
@@ -404,6 +404,20 @@ config USB_G_SERIAL | |||
404 | which includes instructions and a "driver info file" needed to | 404 | which includes instructions and a "driver info file" needed to |
405 | make MS-Windows work with this driver. | 405 | make MS-Windows work with this driver. |
406 | 406 | ||
407 | config USB_MIDI_GADGET | ||
408 | tristate "MIDI Gadget (EXPERIMENTAL)" | ||
409 | depends on SND && EXPERIMENTAL | ||
410 | select SND_RAWMIDI | ||
411 | help | ||
412 | The MIDI Gadget acts as a USB Audio device, with one MIDI | ||
413 | input and one MIDI output. These MIDI jacks appear as | ||
414 | a sound "card" in the ALSA sound system. Other MIDI | ||
415 | connections can then be made on the gadget system, using | ||
416 | ALSA's aconnect utility etc. | ||
417 | |||
418 | Say "y" to link the driver statically, or "m" to build a | ||
419 | dynamically linked module called "g_midi". | ||
420 | |||
407 | 421 | ||
408 | # put drivers that need isochronous transfer support (for audio | 422 | # put drivers that need isochronous transfer support (for audio |
409 | # or video class gadget drivers), or specific hardware, here. | 423 | # or video class gadget drivers), or specific hardware, here. |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 5a28e61392ec..e71e086a1cfa 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_AT91) += at91_udc.o | |||
15 | g_zero-objs := zero.o usbstring.o config.o epautoconf.o | 15 | g_zero-objs := zero.o usbstring.o config.o epautoconf.o |
16 | g_ether-objs := ether.o usbstring.o config.o epautoconf.o | 16 | g_ether-objs := ether.o usbstring.o config.o epautoconf.o |
17 | g_serial-objs := serial.o usbstring.o config.o epautoconf.o | 17 | g_serial-objs := serial.o usbstring.o config.o epautoconf.o |
18 | g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o | ||
18 | gadgetfs-objs := inode.o | 19 | gadgetfs-objs := inode.o |
19 | g_file_storage-objs := file_storage.o usbstring.o config.o \ | 20 | g_file_storage-objs := file_storage.o usbstring.o config.o \ |
20 | epautoconf.o | 21 | epautoconf.o |
@@ -28,4 +29,5 @@ obj-$(CONFIG_USB_ETH) += g_ether.o | |||
28 | obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o | 29 | obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o |
29 | obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o | 30 | obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o |
30 | obj-$(CONFIG_USB_G_SERIAL) += g_serial.o | 31 | obj-$(CONFIG_USB_G_SERIAL) += g_serial.o |
32 | obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o | ||
31 | 33 | ||
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index cfebca05ead5..d00958a01cfb 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
@@ -247,7 +247,7 @@ static int proc_udc_open(struct inode *inode, struct file *file) | |||
247 | return single_open(file, proc_udc_show, PDE(inode)->data); | 247 | return single_open(file, proc_udc_show, PDE(inode)->data); |
248 | } | 248 | } |
249 | 249 | ||
250 | static struct file_operations proc_ops = { | 250 | static const struct file_operations proc_ops = { |
251 | .open = proc_udc_open, | 251 | .open = proc_udc_open, |
252 | .read = seq_read, | 252 | .read = seq_read, |
253 | .llseek = seq_lseek, | 253 | .llseek = seq_lseek, |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 7d1c22c34957..fdab97a27c08 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -889,11 +889,9 @@ EXPORT_SYMBOL (net2280_set_fifo_mode); | |||
889 | static void | 889 | static void |
890 | dummy_gadget_release (struct device *dev) | 890 | dummy_gadget_release (struct device *dev) |
891 | { | 891 | { |
892 | #if 0 /* usb_bus_put isn't EXPORTed! */ | ||
893 | struct dummy *dum = gadget_dev_to_dummy (dev); | 892 | struct dummy *dum = gadget_dev_to_dummy (dev); |
894 | 893 | ||
895 | usb_bus_put (&dummy_to_hcd (dum)->self); | 894 | usb_put_hcd (dummy_to_hcd (dum)); |
896 | #endif | ||
897 | } | 895 | } |
898 | 896 | ||
899 | static int dummy_udc_probe (struct platform_device *pdev) | 897 | static int dummy_udc_probe (struct platform_device *pdev) |
@@ -915,9 +913,7 @@ static int dummy_udc_probe (struct platform_device *pdev) | |||
915 | if (rc < 0) | 913 | if (rc < 0) |
916 | return rc; | 914 | return rc; |
917 | 915 | ||
918 | #if 0 /* usb_bus_get isn't EXPORTed! */ | 916 | usb_get_hcd (dummy_to_hcd (dum)); |
919 | usb_bus_get (&dummy_to_hcd (dum)->self); | ||
920 | #endif | ||
921 | 917 | ||
922 | platform_set_drvdata (pdev, dum); | 918 | platform_set_drvdata (pdev, dum); |
923 | device_create_file (&dum->gadget.dev, &dev_attr_function); | 919 | device_create_file (&dum->gadget.dev, &dev_attr_function); |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 30299c620d97..366dc0a9e52c 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -262,7 +262,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); | |||
262 | #define DEV_CONFIG_CDC | 262 | #define DEV_CONFIG_CDC |
263 | #endif | 263 | #endif |
264 | 264 | ||
265 | #ifdef CONFIG_USB_GADGET_MUSBHDRC | 265 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
266 | #define DEV_CONFIG_CDC | 266 | #define DEV_CONFIG_CDC |
267 | #endif | 267 | #endif |
268 | 268 | ||
@@ -2014,7 +2014,7 @@ rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) | |||
2014 | static int rndis_control_ack (struct net_device *net) | 2014 | static int rndis_control_ack (struct net_device *net) |
2015 | { | 2015 | { |
2016 | struct eth_dev *dev = netdev_priv(net); | 2016 | struct eth_dev *dev = netdev_priv(net); |
2017 | u32 length; | 2017 | int length; |
2018 | struct usb_request *resp = dev->stat_req; | 2018 | struct usb_request *resp = dev->stat_req; |
2019 | 2019 | ||
2020 | /* in case RNDIS calls this after disconnect */ | 2020 | /* in case RNDIS calls this after disconnect */ |
@@ -2230,6 +2230,9 @@ eth_bind (struct usb_gadget *gadget) | |||
2230 | if (gadget_is_pxa (gadget)) { | 2230 | if (gadget_is_pxa (gadget)) { |
2231 | /* pxa doesn't support altsettings */ | 2231 | /* pxa doesn't support altsettings */ |
2232 | cdc = 0; | 2232 | cdc = 0; |
2233 | } else if (gadget_is_musbhdrc(gadget)) { | ||
2234 | /* reduce tx dma overhead by avoiding special cases */ | ||
2235 | zlp = 0; | ||
2233 | } else if (gadget_is_sh(gadget)) { | 2236 | } else if (gadget_is_sh(gadget)) { |
2234 | /* sh doesn't support multiple interfaces or configs */ | 2237 | /* sh doesn't support multiple interfaces or configs */ |
2235 | cdc = 0; | 2238 | cdc = 0; |
@@ -2564,7 +2567,7 @@ static struct usb_gadget_driver eth_driver = { | |||
2564 | 2567 | ||
2565 | .function = (char *) driver_desc, | 2568 | .function = (char *) driver_desc, |
2566 | .bind = eth_bind, | 2569 | .bind = eth_bind, |
2567 | .unbind = __exit_p(eth_unbind), | 2570 | .unbind = eth_unbind, |
2568 | 2571 | ||
2569 | .setup = eth_setup, | 2572 | .setup = eth_setup, |
2570 | .disconnect = eth_disconnect, | 2573 | .disconnect = eth_disconnect, |
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c new file mode 100644 index 000000000000..b68cecd57411 --- /dev/null +++ b/drivers/usb/gadget/gmidi.c | |||
@@ -0,0 +1,1337 @@ | |||
1 | /* | ||
2 | * gmidi.c -- USB MIDI Gadget Driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Thumtronics Pty Ltd. | ||
5 | * Developed for Thumtronics by Grey Innovation | ||
6 | * Ben Williamson <ben.williamson@greyinnovation.com> | ||
7 | * | ||
8 | * This software is distributed under the terms of the GNU General Public | ||
9 | * License ("GPL") version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This code is based in part on: | ||
12 | * | ||
13 | * Gadget Zero driver, Copyright (C) 2003-2004 David Brownell. | ||
14 | * USB Audio driver, Copyright (C) 2002 by Takashi Iwai. | ||
15 | * USB MIDI driver, Copyright (C) 2002-2005 Clemens Ladisch. | ||
16 | * | ||
17 | * Refer to the USB Device Class Definition for MIDI Devices: | ||
18 | * http://www.usb.org/developers/devclass_docs/midi10.pdf | ||
19 | */ | ||
20 | |||
21 | #define DEBUG 1 | ||
22 | // #define VERBOSE | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/utsname.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/moduleparam.h> | ||
33 | |||
34 | #include <sound/driver.h> | ||
35 | #include <sound/core.h> | ||
36 | #include <sound/initval.h> | ||
37 | #include <sound/rawmidi.h> | ||
38 | |||
39 | #include <linux/usb_ch9.h> | ||
40 | #include <linux/usb_gadget.h> | ||
41 | #include <linux/usb/audio.h> | ||
42 | #include <linux/usb/midi.h> | ||
43 | |||
44 | #include "gadget_chips.h" | ||
45 | |||
46 | MODULE_AUTHOR("Ben Williamson"); | ||
47 | MODULE_LICENSE("GPL v2"); | ||
48 | |||
49 | #define DRIVER_VERSION "25 Jul 2006" | ||
50 | |||
51 | static const char shortname[] = "g_midi"; | ||
52 | static const char longname[] = "MIDI Gadget"; | ||
53 | |||
54 | static int index = SNDRV_DEFAULT_IDX1; | ||
55 | static char *id = SNDRV_DEFAULT_STR1; | ||
56 | |||
57 | module_param(index, int, 0444); | ||
58 | MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter."); | ||
59 | module_param(id, charp, 0444); | ||
60 | MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter."); | ||
61 | |||
62 | /* Some systems will want different product identifers published in the | ||
63 | * device descriptor, either numbers or strings or both. These string | ||
64 | * parameters are in UTF-8 (superset of ASCII's 7 bit characters). | ||
65 | */ | ||
66 | |||
67 | static ushort idVendor; | ||
68 | module_param(idVendor, ushort, S_IRUGO); | ||
69 | MODULE_PARM_DESC(idVendor, "USB Vendor ID"); | ||
70 | |||
71 | static ushort idProduct; | ||
72 | module_param(idProduct, ushort, S_IRUGO); | ||
73 | MODULE_PARM_DESC(idProduct, "USB Product ID"); | ||
74 | |||
75 | static ushort bcdDevice; | ||
76 | module_param(bcdDevice, ushort, S_IRUGO); | ||
77 | MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); | ||
78 | |||
79 | static char *iManufacturer; | ||
80 | module_param(iManufacturer, charp, S_IRUGO); | ||
81 | MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); | ||
82 | |||
83 | static char *iProduct; | ||
84 | module_param(iProduct, charp, S_IRUGO); | ||
85 | MODULE_PARM_DESC(iProduct, "USB Product string"); | ||
86 | |||
87 | static char *iSerialNumber; | ||
88 | module_param(iSerialNumber, charp, S_IRUGO); | ||
89 | MODULE_PARM_DESC(iSerialNumber, "SerialNumber"); | ||
90 | |||
91 | /* | ||
92 | * this version autoconfigures as much as possible, | ||
93 | * which is reasonable for most "bulk-only" drivers. | ||
94 | */ | ||
95 | static const char *EP_IN_NAME; | ||
96 | static const char *EP_OUT_NAME; | ||
97 | |||
98 | |||
99 | /* big enough to hold our biggest descriptor */ | ||
100 | #define USB_BUFSIZ 256 | ||
101 | |||
102 | |||
103 | /* This is a gadget, and the IN/OUT naming is from the host's perspective. | ||
104 | USB -> OUT endpoint -> rawmidi | ||
105 | USB <- IN endpoint <- rawmidi */ | ||
106 | struct gmidi_in_port { | ||
107 | struct gmidi_device* dev; | ||
108 | int active; | ||
109 | uint8_t cable; /* cable number << 4 */ | ||
110 | uint8_t state; | ||
111 | #define STATE_UNKNOWN 0 | ||
112 | #define STATE_1PARAM 1 | ||
113 | #define STATE_2PARAM_1 2 | ||
114 | #define STATE_2PARAM_2 3 | ||
115 | #define STATE_SYSEX_0 4 | ||
116 | #define STATE_SYSEX_1 5 | ||
117 | #define STATE_SYSEX_2 6 | ||
118 | uint8_t data[2]; | ||
119 | }; | ||
120 | |||
121 | struct gmidi_device { | ||
122 | spinlock_t lock; | ||
123 | struct usb_gadget *gadget; | ||
124 | struct usb_request *req; /* for control responses */ | ||
125 | u8 config; | ||
126 | struct usb_ep *in_ep, *out_ep; | ||
127 | struct snd_card *card; | ||
128 | struct snd_rawmidi *rmidi; | ||
129 | struct snd_rawmidi_substream *in_substream; | ||
130 | struct snd_rawmidi_substream *out_substream; | ||
131 | |||
132 | /* For the moment we only support one port in | ||
133 | each direction, but in_port is kept as a | ||
134 | separate struct so we can have more later. */ | ||
135 | struct gmidi_in_port in_port; | ||
136 | unsigned long out_triggered; | ||
137 | struct tasklet_struct tasklet; | ||
138 | }; | ||
139 | |||
140 | static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req); | ||
141 | |||
142 | |||
143 | #define xprintk(d,level,fmt,args...) \ | ||
144 | dev_printk(level , &(d)->gadget->dev , fmt , ## args) | ||
145 | |||
146 | #ifdef DEBUG | ||
147 | #define DBG(dev,fmt,args...) \ | ||
148 | xprintk(dev , KERN_DEBUG , fmt , ## args) | ||
149 | #else | ||
150 | #define DBG(dev,fmt,args...) \ | ||
151 | do { } while (0) | ||
152 | #endif /* DEBUG */ | ||
153 | |||
154 | #ifdef VERBOSE | ||
155 | #define VDBG DBG | ||
156 | #else | ||
157 | #define VDBG(dev,fmt,args...) \ | ||
158 | do { } while (0) | ||
159 | #endif /* VERBOSE */ | ||
160 | |||
161 | #define ERROR(dev,fmt,args...) \ | ||
162 | xprintk(dev , KERN_ERR , fmt , ## args) | ||
163 | #define WARN(dev,fmt,args...) \ | ||
164 | xprintk(dev , KERN_WARNING , fmt , ## args) | ||
165 | #define INFO(dev,fmt,args...) \ | ||
166 | xprintk(dev , KERN_INFO , fmt , ## args) | ||
167 | |||
168 | |||
169 | static unsigned buflen = 256; | ||
170 | static unsigned qlen = 32; | ||
171 | |||
172 | module_param(buflen, uint, S_IRUGO); | ||
173 | module_param(qlen, uint, S_IRUGO); | ||
174 | |||
175 | |||
176 | /* Thanks to Grey Innovation for donating this product ID. | ||
177 | * | ||
178 | * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! | ||
179 | * Instead: allocate your own, using normal USB-IF procedures. | ||
180 | */ | ||
181 | #define DRIVER_VENDOR_NUM 0x17b3 /* Grey Innovation */ | ||
182 | #define DRIVER_PRODUCT_NUM 0x0004 /* Linux-USB "MIDI Gadget" */ | ||
183 | |||
184 | |||
185 | /* | ||
186 | * DESCRIPTORS ... most are static, but strings and (full) | ||
187 | * configuration descriptors are built on demand. | ||
188 | */ | ||
189 | |||
190 | #define STRING_MANUFACTURER 25 | ||
191 | #define STRING_PRODUCT 42 | ||
192 | #define STRING_SERIAL 101 | ||
193 | #define STRING_MIDI_GADGET 250 | ||
194 | |||
195 | /* We only have the one configuration, it's number 1. */ | ||
196 | #define GMIDI_CONFIG 1 | ||
197 | |||
198 | /* We have two interfaces- AudioControl and MIDIStreaming */ | ||
199 | #define GMIDI_AC_INTERFACE 0 | ||
200 | #define GMIDI_MS_INTERFACE 1 | ||
201 | #define GMIDI_NUM_INTERFACES 2 | ||
202 | |||
203 | DECLARE_USB_AC_HEADER_DESCRIPTOR(1); | ||
204 | DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); | ||
205 | DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); | ||
206 | |||
207 | /* B.1 Device Descriptor */ | ||
208 | static struct usb_device_descriptor device_desc = { | ||
209 | .bLength = USB_DT_DEVICE_SIZE, | ||
210 | .bDescriptorType = USB_DT_DEVICE, | ||
211 | .bcdUSB = __constant_cpu_to_le16(0x0200), | ||
212 | .bDeviceClass = USB_CLASS_PER_INTERFACE, | ||
213 | .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), | ||
214 | .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), | ||
215 | .iManufacturer = STRING_MANUFACTURER, | ||
216 | .iProduct = STRING_PRODUCT, | ||
217 | .bNumConfigurations = 1, | ||
218 | }; | ||
219 | |||
220 | /* B.2 Configuration Descriptor */ | ||
221 | static struct usb_config_descriptor config_desc = { | ||
222 | .bLength = USB_DT_CONFIG_SIZE, | ||
223 | .bDescriptorType = USB_DT_CONFIG, | ||
224 | /* compute wTotalLength on the fly */ | ||
225 | .bNumInterfaces = GMIDI_NUM_INTERFACES, | ||
226 | .bConfigurationValue = GMIDI_CONFIG, | ||
227 | .iConfiguration = STRING_MIDI_GADGET, | ||
228 | /* | ||
229 | * FIXME: When embedding this driver in a device, | ||
230 | * these need to be set to reflect the actual | ||
231 | * power properties of the device. Is it selfpowered? | ||
232 | */ | ||
233 | .bmAttributes = USB_CONFIG_ATT_ONE, | ||
234 | .bMaxPower = 1, | ||
235 | }; | ||
236 | |||
237 | /* B.3.1 Standard AC Interface Descriptor */ | ||
238 | static const struct usb_interface_descriptor ac_interface_desc = { | ||
239 | .bLength = USB_DT_INTERFACE_SIZE, | ||
240 | .bDescriptorType = USB_DT_INTERFACE, | ||
241 | .bInterfaceNumber = GMIDI_AC_INTERFACE, | ||
242 | .bNumEndpoints = 0, | ||
243 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
244 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, | ||
245 | .iInterface = STRING_MIDI_GADGET, | ||
246 | }; | ||
247 | |||
248 | /* B.3.2 Class-Specific AC Interface Descriptor */ | ||
249 | static const struct usb_ac_header_descriptor_1 ac_header_desc = { | ||
250 | .bLength = USB_DT_AC_HEADER_SIZE(1), | ||
251 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
252 | .bDescriptorSubtype = USB_MS_HEADER, | ||
253 | .bcdADC = __constant_cpu_to_le16(0x0100), | ||
254 | .wTotalLength = USB_DT_AC_HEADER_SIZE(1), | ||
255 | .bInCollection = 1, | ||
256 | .baInterfaceNr = { | ||
257 | [0] = GMIDI_MS_INTERFACE, | ||
258 | } | ||
259 | }; | ||
260 | |||
261 | /* B.4.1 Standard MS Interface Descriptor */ | ||
262 | static const struct usb_interface_descriptor ms_interface_desc = { | ||
263 | .bLength = USB_DT_INTERFACE_SIZE, | ||
264 | .bDescriptorType = USB_DT_INTERFACE, | ||
265 | .bInterfaceNumber = GMIDI_MS_INTERFACE, | ||
266 | .bNumEndpoints = 2, | ||
267 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
268 | .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, | ||
269 | .iInterface = STRING_MIDI_GADGET, | ||
270 | }; | ||
271 | |||
272 | /* B.4.2 Class-Specific MS Interface Descriptor */ | ||
273 | static const struct usb_ms_header_descriptor ms_header_desc = { | ||
274 | .bLength = USB_DT_MS_HEADER_SIZE, | ||
275 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
276 | .bDescriptorSubtype = USB_MS_HEADER, | ||
277 | .bcdMSC = __constant_cpu_to_le16(0x0100), | ||
278 | .wTotalLength = USB_DT_MS_HEADER_SIZE | ||
279 | + 2*USB_DT_MIDI_IN_SIZE | ||
280 | + 2*USB_DT_MIDI_OUT_SIZE(1), | ||
281 | }; | ||
282 | |||
283 | #define JACK_IN_EMB 1 | ||
284 | #define JACK_IN_EXT 2 | ||
285 | #define JACK_OUT_EMB 3 | ||
286 | #define JACK_OUT_EXT 4 | ||
287 | |||
288 | /* B.4.3 MIDI IN Jack Descriptors */ | ||
289 | static const struct usb_midi_in_jack_descriptor jack_in_emb_desc = { | ||
290 | .bLength = USB_DT_MIDI_IN_SIZE, | ||
291 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
292 | .bDescriptorSubtype = USB_MS_MIDI_IN_JACK, | ||
293 | .bJackType = USB_MS_EMBEDDED, | ||
294 | .bJackID = JACK_IN_EMB, | ||
295 | }; | ||
296 | |||
297 | static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = { | ||
298 | .bLength = USB_DT_MIDI_IN_SIZE, | ||
299 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
300 | .bDescriptorSubtype = USB_MS_MIDI_IN_JACK, | ||
301 | .bJackType = USB_MS_EXTERNAL, | ||
302 | .bJackID = JACK_IN_EXT, | ||
303 | }; | ||
304 | |||
305 | /* B.4.4 MIDI OUT Jack Descriptors */ | ||
306 | static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = { | ||
307 | .bLength = USB_DT_MIDI_OUT_SIZE(1), | ||
308 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
309 | .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK, | ||
310 | .bJackType = USB_MS_EMBEDDED, | ||
311 | .bJackID = JACK_OUT_EMB, | ||
312 | .bNrInputPins = 1, | ||
313 | .pins = { | ||
314 | [0] = { | ||
315 | .baSourceID = JACK_IN_EXT, | ||
316 | .baSourcePin = 1, | ||
317 | } | ||
318 | } | ||
319 | }; | ||
320 | |||
321 | static const struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc = { | ||
322 | .bLength = USB_DT_MIDI_OUT_SIZE(1), | ||
323 | .bDescriptorType = USB_DT_CS_INTERFACE, | ||
324 | .bDescriptorSubtype = USB_MS_MIDI_OUT_JACK, | ||
325 | .bJackType = USB_MS_EXTERNAL, | ||
326 | .bJackID = JACK_OUT_EXT, | ||
327 | .bNrInputPins = 1, | ||
328 | .pins = { | ||
329 | [0] = { | ||
330 | .baSourceID = JACK_IN_EMB, | ||
331 | .baSourcePin = 1, | ||
332 | } | ||
333 | } | ||
334 | }; | ||
335 | |||
336 | /* B.5.1 Standard Bulk OUT Endpoint Descriptor */ | ||
337 | static struct usb_endpoint_descriptor bulk_out_desc = { | ||
338 | .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | ||
339 | .bDescriptorType = USB_DT_ENDPOINT, | ||
340 | .bEndpointAddress = USB_DIR_OUT, | ||
341 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
342 | }; | ||
343 | |||
344 | /* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */ | ||
345 | static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = { | ||
346 | .bLength = USB_DT_MS_ENDPOINT_SIZE(1), | ||
347 | .bDescriptorType = USB_DT_CS_ENDPOINT, | ||
348 | .bDescriptorSubtype = USB_MS_GENERAL, | ||
349 | .bNumEmbMIDIJack = 1, | ||
350 | .baAssocJackID = { | ||
351 | [0] = JACK_IN_EMB, | ||
352 | } | ||
353 | }; | ||
354 | |||
355 | /* B.6.1 Standard Bulk IN Endpoint Descriptor */ | ||
356 | static struct usb_endpoint_descriptor bulk_in_desc = { | ||
357 | .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, | ||
358 | .bDescriptorType = USB_DT_ENDPOINT, | ||
359 | .bEndpointAddress = USB_DIR_IN, | ||
360 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
361 | }; | ||
362 | |||
363 | /* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */ | ||
364 | static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = { | ||
365 | .bLength = USB_DT_MS_ENDPOINT_SIZE(1), | ||
366 | .bDescriptorType = USB_DT_CS_ENDPOINT, | ||
367 | .bDescriptorSubtype = USB_MS_GENERAL, | ||
368 | .bNumEmbMIDIJack = 1, | ||
369 | .baAssocJackID = { | ||
370 | [0] = JACK_OUT_EMB, | ||
371 | } | ||
372 | }; | ||
373 | |||
374 | static const struct usb_descriptor_header *gmidi_function [] = { | ||
375 | (struct usb_descriptor_header *)&ac_interface_desc, | ||
376 | (struct usb_descriptor_header *)&ac_header_desc, | ||
377 | (struct usb_descriptor_header *)&ms_interface_desc, | ||
378 | |||
379 | (struct usb_descriptor_header *)&ms_header_desc, | ||
380 | (struct usb_descriptor_header *)&jack_in_emb_desc, | ||
381 | (struct usb_descriptor_header *)&jack_in_ext_desc, | ||
382 | (struct usb_descriptor_header *)&jack_out_emb_desc, | ||
383 | (struct usb_descriptor_header *)&jack_out_ext_desc, | ||
384 | /* If you add more jacks, update ms_header_desc.wTotalLength */ | ||
385 | |||
386 | (struct usb_descriptor_header *)&bulk_out_desc, | ||
387 | (struct usb_descriptor_header *)&ms_out_desc, | ||
388 | (struct usb_descriptor_header *)&bulk_in_desc, | ||
389 | (struct usb_descriptor_header *)&ms_in_desc, | ||
390 | NULL, | ||
391 | }; | ||
392 | |||
393 | static char manufacturer[50]; | ||
394 | static char product_desc[40] = "MIDI Gadget"; | ||
395 | static char serial_number[20]; | ||
396 | |||
397 | /* static strings, in UTF-8 */ | ||
398 | static struct usb_string strings [] = { | ||
399 | { STRING_MANUFACTURER, manufacturer, }, | ||
400 | { STRING_PRODUCT, product_desc, }, | ||
401 | { STRING_SERIAL, serial_number, }, | ||
402 | { STRING_MIDI_GADGET, longname, }, | ||
403 | { } /* end of list */ | ||
404 | }; | ||
405 | |||
406 | static struct usb_gadget_strings stringtab = { | ||
407 | .language = 0x0409, /* en-us */ | ||
408 | .strings = strings, | ||
409 | }; | ||
410 | |||
411 | static int config_buf(struct usb_gadget *gadget, | ||
412 | u8 *buf, u8 type, unsigned index) | ||
413 | { | ||
414 | int len; | ||
415 | |||
416 | /* only one configuration */ | ||
417 | if (index != 0) { | ||
418 | return -EINVAL; | ||
419 | } | ||
420 | len = usb_gadget_config_buf(&config_desc, | ||
421 | buf, USB_BUFSIZ, gmidi_function); | ||
422 | if (len < 0) { | ||
423 | return len; | ||
424 | } | ||
425 | ((struct usb_config_descriptor *)buf)->bDescriptorType = type; | ||
426 | return len; | ||
427 | } | ||
428 | |||
429 | static struct usb_request* alloc_ep_req(struct usb_ep *ep, unsigned length) | ||
430 | { | ||
431 | struct usb_request *req; | ||
432 | |||
433 | req = usb_ep_alloc_request(ep, GFP_ATOMIC); | ||
434 | if (req) { | ||
435 | req->length = length; | ||
436 | req->buf = kmalloc(length, GFP_ATOMIC); | ||
437 | if (!req->buf) { | ||
438 | usb_ep_free_request(ep, req); | ||
439 | req = NULL; | ||
440 | } | ||
441 | } | ||
442 | return req; | ||
443 | } | ||
444 | |||
445 | static void free_ep_req(struct usb_ep *ep, struct usb_request *req) | ||
446 | { | ||
447 | kfree(req->buf); | ||
448 | usb_ep_free_request(ep, req); | ||
449 | } | ||
450 | |||
451 | static const uint8_t gmidi_cin_length[] = { | ||
452 | 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 | ||
453 | }; | ||
454 | |||
455 | /* | ||
456 | * Receives a chunk of MIDI data. | ||
457 | */ | ||
458 | static void gmidi_read_data(struct usb_ep *ep, int cable, | ||
459 | uint8_t* data, int length) | ||
460 | { | ||
461 | struct gmidi_device *dev = ep->driver_data; | ||
462 | /* cable is ignored, because for now we only have one. */ | ||
463 | |||
464 | if (!dev->out_substream) { | ||
465 | /* Nobody is listening - throw it on the floor. */ | ||
466 | return; | ||
467 | } | ||
468 | if (!test_bit(dev->out_substream->number, &dev->out_triggered)) { | ||
469 | return; | ||
470 | } | ||
471 | snd_rawmidi_receive(dev->out_substream, data, length); | ||
472 | } | ||
473 | |||
474 | static void gmidi_handle_out_data(struct usb_ep *ep, struct usb_request *req) | ||
475 | { | ||
476 | unsigned i; | ||
477 | u8 *buf = req->buf; | ||
478 | |||
479 | for (i = 0; i + 3 < req->actual; i += 4) { | ||
480 | if (buf[i] != 0) { | ||
481 | int cable = buf[i] >> 4; | ||
482 | int length = gmidi_cin_length[buf[i] & 0x0f]; | ||
483 | gmidi_read_data(ep, cable, &buf[i + 1], length); | ||
484 | } | ||
485 | } | ||
486 | } | ||
487 | |||
488 | static void gmidi_complete(struct usb_ep *ep, struct usb_request *req) | ||
489 | { | ||
490 | struct gmidi_device *dev = ep->driver_data; | ||
491 | int status = req->status; | ||
492 | |||
493 | switch (status) { | ||
494 | case 0: /* normal completion */ | ||
495 | if (ep == dev->out_ep) { | ||
496 | /* we received stuff. | ||
497 | req is queued again, below */ | ||
498 | gmidi_handle_out_data(ep, req); | ||
499 | } else if (ep == dev->in_ep) { | ||
500 | /* our transmit completed. | ||
501 | see if there's more to go. | ||
502 | gmidi_transmit eats req, don't queue it again. */ | ||
503 | gmidi_transmit(dev, req); | ||
504 | return; | ||
505 | } | ||
506 | break; | ||
507 | |||
508 | /* this endpoint is normally active while we're configured */ | ||
509 | case -ECONNABORTED: /* hardware forced ep reset */ | ||
510 | case -ECONNRESET: /* request dequeued */ | ||
511 | case -ESHUTDOWN: /* disconnect from host */ | ||
512 | VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, | ||
513 | req->actual, req->length); | ||
514 | if (ep == dev->out_ep) { | ||
515 | gmidi_handle_out_data(ep, req); | ||
516 | } | ||
517 | free_ep_req(ep, req); | ||
518 | return; | ||
519 | |||
520 | case -EOVERFLOW: /* buffer overrun on read means that | ||
521 | * we didn't provide a big enough | ||
522 | * buffer. | ||
523 | */ | ||
524 | default: | ||
525 | DBG(dev, "%s complete --> %d, %d/%d\n", ep->name, | ||
526 | status, req->actual, req->length); | ||
527 | break; | ||
528 | case -EREMOTEIO: /* short read */ | ||
529 | break; | ||
530 | } | ||
531 | |||
532 | status = usb_ep_queue(ep, req, GFP_ATOMIC); | ||
533 | if (status) { | ||
534 | ERROR(dev, "kill %s: resubmit %d bytes --> %d\n", | ||
535 | ep->name, req->length, status); | ||
536 | usb_ep_set_halt(ep); | ||
537 | /* FIXME recover later ... somehow */ | ||
538 | } | ||
539 | } | ||
540 | |||
541 | static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags) | ||
542 | { | ||
543 | int err = 0; | ||
544 | struct usb_request *req; | ||
545 | struct usb_ep* ep; | ||
546 | unsigned i; | ||
547 | |||
548 | err = usb_ep_enable(dev->in_ep, &bulk_in_desc); | ||
549 | if (err) { | ||
550 | ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err); | ||
551 | goto fail; | ||
552 | } | ||
553 | dev->in_ep->driver_data = dev; | ||
554 | |||
555 | err = usb_ep_enable(dev->out_ep, &bulk_out_desc); | ||
556 | if (err) { | ||
557 | ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err); | ||
558 | goto fail; | ||
559 | } | ||
560 | dev->out_ep->driver_data = dev; | ||
561 | |||
562 | /* allocate a bunch of read buffers and queue them all at once. */ | ||
563 | ep = dev->out_ep; | ||
564 | for (i = 0; i < qlen && err == 0; i++) { | ||
565 | req = alloc_ep_req(ep, buflen); | ||
566 | if (req) { | ||
567 | req->complete = gmidi_complete; | ||
568 | err = usb_ep_queue(ep, req, GFP_ATOMIC); | ||
569 | if (err) { | ||
570 | DBG(dev, "%s queue req: %d\n", ep->name, err); | ||
571 | } | ||
572 | } else { | ||
573 | err = -ENOMEM; | ||
574 | } | ||
575 | } | ||
576 | fail: | ||
577 | /* caller is responsible for cleanup on error */ | ||
578 | return err; | ||
579 | } | ||
580 | |||
581 | |||
582 | static void gmidi_reset_config(struct gmidi_device *dev) | ||
583 | { | ||
584 | if (dev->config == 0) { | ||
585 | return; | ||
586 | } | ||
587 | |||
588 | DBG(dev, "reset config\n"); | ||
589 | |||
590 | /* just disable endpoints, forcing completion of pending i/o. | ||
591 | * all our completion handlers free their requests in this case. | ||
592 | */ | ||
593 | usb_ep_disable(dev->in_ep); | ||
594 | usb_ep_disable(dev->out_ep); | ||
595 | dev->config = 0; | ||
596 | } | ||
597 | |||
598 | /* change our operational config. this code must agree with the code | ||
599 | * that returns config descriptors, and altsetting code. | ||
600 | * | ||
601 | * it's also responsible for power management interactions. some | ||
602 | * configurations might not work with our current power sources. | ||
603 | * | ||
604 | * note that some device controller hardware will constrain what this | ||
605 | * code can do, perhaps by disallowing more than one configuration or | ||
606 | * by limiting configuration choices (like the pxa2xx). | ||
607 | */ | ||
608 | static int | ||
609 | gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags) | ||
610 | { | ||
611 | int result = 0; | ||
612 | struct usb_gadget *gadget = dev->gadget; | ||
613 | |||
614 | #if 0 | ||
615 | /* FIXME */ | ||
616 | /* Hacking this bit out fixes a bug where on receipt of two | ||
617 | USB_REQ_SET_CONFIGURATION messages, we end up with no | ||
618 | buffered OUT requests waiting for data. This is clearly | ||
619 | hiding a bug elsewhere, because if the config didn't | ||
620 | change then we really shouldn't do anything. */ | ||
621 | /* Having said that, when we do "change" from config 1 | ||
622 | to config 1, we at least gmidi_reset_config() which | ||
623 | clears out any requests on endpoints, so it's not like | ||
624 | we leak or anything. */ | ||
625 | if (number == dev->config) { | ||
626 | return 0; | ||
627 | } | ||
628 | #endif | ||
629 | |||
630 | if (gadget_is_sa1100(gadget) && dev->config) { | ||
631 | /* tx fifo is full, but we can't clear it...*/ | ||
632 | INFO(dev, "can't change configurations\n"); | ||
633 | return -ESPIPE; | ||
634 | } | ||
635 | gmidi_reset_config(dev); | ||
636 | |||
637 | switch (number) { | ||
638 | case GMIDI_CONFIG: | ||
639 | result = set_gmidi_config(dev, gfp_flags); | ||
640 | break; | ||
641 | default: | ||
642 | result = -EINVAL; | ||
643 | /* FALL THROUGH */ | ||
644 | case 0: | ||
645 | return result; | ||
646 | } | ||
647 | |||
648 | if (!result && (!dev->in_ep || !dev->out_ep)) { | ||
649 | result = -ENODEV; | ||
650 | } | ||
651 | if (result) { | ||
652 | gmidi_reset_config(dev); | ||
653 | } else { | ||
654 | char *speed; | ||
655 | |||
656 | switch (gadget->speed) { | ||
657 | case USB_SPEED_LOW: speed = "low"; break; | ||
658 | case USB_SPEED_FULL: speed = "full"; break; | ||
659 | case USB_SPEED_HIGH: speed = "high"; break; | ||
660 | default: speed = "?"; break; | ||
661 | } | ||
662 | |||
663 | dev->config = number; | ||
664 | INFO(dev, "%s speed\n", speed); | ||
665 | } | ||
666 | return result; | ||
667 | } | ||
668 | |||
669 | |||
670 | static void gmidi_setup_complete(struct usb_ep *ep, struct usb_request *req) | ||
671 | { | ||
672 | if (req->status || req->actual != req->length) { | ||
673 | DBG((struct gmidi_device *) ep->driver_data, | ||
674 | "setup complete --> %d, %d/%d\n", | ||
675 | req->status, req->actual, req->length); | ||
676 | } | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * The setup() callback implements all the ep0 functionality that's | ||
681 | * not handled lower down, in hardware or the hardware driver (like | ||
682 | * device and endpoint feature flags, and their status). It's all | ||
683 | * housekeeping for the gadget function we're implementing. Most of | ||
684 | * the work is in config-specific setup. | ||
685 | */ | ||
686 | static int gmidi_setup(struct usb_gadget *gadget, | ||
687 | const struct usb_ctrlrequest *ctrl) | ||
688 | { | ||
689 | struct gmidi_device *dev = get_gadget_data(gadget); | ||
690 | struct usb_request *req = dev->req; | ||
691 | int value = -EOPNOTSUPP; | ||
692 | u16 w_index = le16_to_cpu(ctrl->wIndex); | ||
693 | u16 w_value = le16_to_cpu(ctrl->wValue); | ||
694 | u16 w_length = le16_to_cpu(ctrl->wLength); | ||
695 | |||
696 | /* usually this stores reply data in the pre-allocated ep0 buffer, | ||
697 | * but config change events will reconfigure hardware. | ||
698 | */ | ||
699 | req->zero = 0; | ||
700 | switch (ctrl->bRequest) { | ||
701 | |||
702 | case USB_REQ_GET_DESCRIPTOR: | ||
703 | if (ctrl->bRequestType != USB_DIR_IN) { | ||
704 | goto unknown; | ||
705 | } | ||
706 | switch (w_value >> 8) { | ||
707 | |||
708 | case USB_DT_DEVICE: | ||
709 | value = min(w_length, (u16) sizeof(device_desc)); | ||
710 | memcpy(req->buf, &device_desc, value); | ||
711 | break; | ||
712 | case USB_DT_CONFIG: | ||
713 | value = config_buf(gadget, req->buf, | ||
714 | w_value >> 8, | ||
715 | w_value & 0xff); | ||
716 | if (value >= 0) { | ||
717 | value = min(w_length, (u16)value); | ||
718 | } | ||
719 | break; | ||
720 | |||
721 | case USB_DT_STRING: | ||
722 | /* wIndex == language code. | ||
723 | * this driver only handles one language, you can | ||
724 | * add string tables for other languages, using | ||
725 | * any UTF-8 characters | ||
726 | */ | ||
727 | value = usb_gadget_get_string(&stringtab, | ||
728 | w_value & 0xff, req->buf); | ||
729 | if (value >= 0) { | ||
730 | value = min(w_length, (u16)value); | ||
731 | } | ||
732 | break; | ||
733 | } | ||
734 | break; | ||
735 | |||
736 | /* currently two configs, two speeds */ | ||
737 | case USB_REQ_SET_CONFIGURATION: | ||
738 | if (ctrl->bRequestType != 0) { | ||
739 | goto unknown; | ||
740 | } | ||
741 | if (gadget->a_hnp_support) { | ||
742 | DBG(dev, "HNP available\n"); | ||
743 | } else if (gadget->a_alt_hnp_support) { | ||
744 | DBG(dev, "HNP needs a different root port\n"); | ||
745 | } else { | ||
746 | VDBG(dev, "HNP inactive\n"); | ||
747 | } | ||
748 | spin_lock(&dev->lock); | ||
749 | value = gmidi_set_config(dev, w_value, GFP_ATOMIC); | ||
750 | spin_unlock(&dev->lock); | ||
751 | break; | ||
752 | case USB_REQ_GET_CONFIGURATION: | ||
753 | if (ctrl->bRequestType != USB_DIR_IN) { | ||
754 | goto unknown; | ||
755 | } | ||
756 | *(u8 *)req->buf = dev->config; | ||
757 | value = min(w_length, (u16)1); | ||
758 | break; | ||
759 | |||
760 | /* until we add altsetting support, or other interfaces, | ||
761 | * only 0/0 are possible. pxa2xx only supports 0/0 (poorly) | ||
762 | * and already killed pending endpoint I/O. | ||
763 | */ | ||
764 | case USB_REQ_SET_INTERFACE: | ||
765 | if (ctrl->bRequestType != USB_RECIP_INTERFACE) { | ||
766 | goto unknown; | ||
767 | } | ||
768 | spin_lock(&dev->lock); | ||
769 | if (dev->config && w_index < GMIDI_NUM_INTERFACES | ||
770 | && w_value == 0) | ||
771 | { | ||
772 | u8 config = dev->config; | ||
773 | |||
774 | /* resets interface configuration, forgets about | ||
775 | * previous transaction state (queued bufs, etc) | ||
776 | * and re-inits endpoint state (toggle etc) | ||
777 | * no response queued, just zero status == success. | ||
778 | * if we had more than one interface we couldn't | ||
779 | * use this "reset the config" shortcut. | ||
780 | */ | ||
781 | gmidi_reset_config(dev); | ||
782 | gmidi_set_config(dev, config, GFP_ATOMIC); | ||
783 | value = 0; | ||
784 | } | ||
785 | spin_unlock(&dev->lock); | ||
786 | break; | ||
787 | case USB_REQ_GET_INTERFACE: | ||
788 | if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) { | ||
789 | goto unknown; | ||
790 | } | ||
791 | if (!dev->config) { | ||
792 | break; | ||
793 | } | ||
794 | if (w_index >= GMIDI_NUM_INTERFACES) { | ||
795 | value = -EDOM; | ||
796 | break; | ||
797 | } | ||
798 | *(u8 *)req->buf = 0; | ||
799 | value = min(w_length, (u16)1); | ||
800 | break; | ||
801 | |||
802 | default: | ||
803 | unknown: | ||
804 | VDBG(dev, "unknown control req%02x.%02x v%04x i%04x l%d\n", | ||
805 | ctrl->bRequestType, ctrl->bRequest, | ||
806 | w_value, w_index, w_length); | ||
807 | } | ||
808 | |||
809 | /* respond with data transfer before status phase? */ | ||
810 | if (value >= 0) { | ||
811 | req->length = value; | ||
812 | req->zero = value < w_length; | ||
813 | value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); | ||
814 | if (value < 0) { | ||
815 | DBG(dev, "ep_queue --> %d\n", value); | ||
816 | req->status = 0; | ||
817 | gmidi_setup_complete(gadget->ep0, req); | ||
818 | } | ||
819 | } | ||
820 | |||
821 | /* device either stalls (value < 0) or reports success */ | ||
822 | return value; | ||
823 | } | ||
824 | |||
825 | static void gmidi_disconnect(struct usb_gadget *gadget) | ||
826 | { | ||
827 | struct gmidi_device *dev = get_gadget_data(gadget); | ||
828 | unsigned long flags; | ||
829 | |||
830 | spin_lock_irqsave(&dev->lock, flags); | ||
831 | gmidi_reset_config(dev); | ||
832 | |||
833 | /* a more significant application might have some non-usb | ||
834 | * activities to quiesce here, saving resources like power | ||
835 | * or pushing the notification up a network stack. | ||
836 | */ | ||
837 | spin_unlock_irqrestore(&dev->lock, flags); | ||
838 | |||
839 | /* next we may get setup() calls to enumerate new connections; | ||
840 | * or an unbind() during shutdown (including removing module). | ||
841 | */ | ||
842 | } | ||
843 | |||
844 | static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget) | ||
845 | { | ||
846 | struct gmidi_device *dev = get_gadget_data(gadget); | ||
847 | struct snd_card* card; | ||
848 | |||
849 | DBG(dev, "unbind\n"); | ||
850 | |||
851 | card = dev->card; | ||
852 | dev->card = NULL; | ||
853 | if (card) { | ||
854 | snd_card_free(card); | ||
855 | } | ||
856 | |||
857 | /* we've already been disconnected ... no i/o is active */ | ||
858 | if (dev->req) { | ||
859 | dev->req->length = USB_BUFSIZ; | ||
860 | free_ep_req(gadget->ep0, dev->req); | ||
861 | } | ||
862 | kfree(dev); | ||
863 | set_gadget_data(gadget, NULL); | ||
864 | } | ||
865 | |||
866 | static int gmidi_snd_free(struct snd_device *device) | ||
867 | { | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static void gmidi_transmit_packet(struct usb_request* req, uint8_t p0, | ||
872 | uint8_t p1, uint8_t p2, uint8_t p3) | ||
873 | { | ||
874 | unsigned length = req->length; | ||
875 | |||
876 | uint8_t* buf = (uint8_t*)req->buf + length; | ||
877 | buf[0] = p0; | ||
878 | buf[1] = p1; | ||
879 | buf[2] = p2; | ||
880 | buf[3] = p3; | ||
881 | req->length = length + 4; | ||
882 | } | ||
883 | |||
884 | /* | ||
885 | * Converts MIDI commands to USB MIDI packets. | ||
886 | */ | ||
887 | static void gmidi_transmit_byte(struct usb_request* req, | ||
888 | struct gmidi_in_port* port, uint8_t b) | ||
889 | { | ||
890 | uint8_t p0 = port->cable; | ||
891 | |||
892 | if (b >= 0xf8) { | ||
893 | gmidi_transmit_packet(req, p0 | 0x0f, b, 0, 0); | ||
894 | } else if (b >= 0xf0) { | ||
895 | switch (b) { | ||
896 | case 0xf0: | ||
897 | port->data[0] = b; | ||
898 | port->state = STATE_SYSEX_1; | ||
899 | break; | ||
900 | case 0xf1: | ||
901 | case 0xf3: | ||
902 | port->data[0] = b; | ||
903 | port->state = STATE_1PARAM; | ||
904 | break; | ||
905 | case 0xf2: | ||
906 | port->data[0] = b; | ||
907 | port->state = STATE_2PARAM_1; | ||
908 | break; | ||
909 | case 0xf4: | ||
910 | case 0xf5: | ||
911 | port->state = STATE_UNKNOWN; | ||
912 | break; | ||
913 | case 0xf6: | ||
914 | gmidi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0); | ||
915 | port->state = STATE_UNKNOWN; | ||
916 | break; | ||
917 | case 0xf7: | ||
918 | switch (port->state) { | ||
919 | case STATE_SYSEX_0: | ||
920 | gmidi_transmit_packet(req, | ||
921 | p0 | 0x05, 0xf7, 0, 0); | ||
922 | break; | ||
923 | case STATE_SYSEX_1: | ||
924 | gmidi_transmit_packet(req, | ||
925 | p0 | 0x06, port->data[0], 0xf7, 0); | ||
926 | break; | ||
927 | case STATE_SYSEX_2: | ||
928 | gmidi_transmit_packet(req, | ||
929 | p0 | 0x07, port->data[0], | ||
930 | port->data[1], 0xf7); | ||
931 | break; | ||
932 | } | ||
933 | port->state = STATE_UNKNOWN; | ||
934 | break; | ||
935 | } | ||
936 | } else if (b >= 0x80) { | ||
937 | port->data[0] = b; | ||
938 | if (b >= 0xc0 && b <= 0xdf) | ||
939 | port->state = STATE_1PARAM; | ||
940 | else | ||
941 | port->state = STATE_2PARAM_1; | ||
942 | } else { /* b < 0x80 */ | ||
943 | switch (port->state) { | ||
944 | case STATE_1PARAM: | ||
945 | if (port->data[0] < 0xf0) { | ||
946 | p0 |= port->data[0] >> 4; | ||
947 | } else { | ||
948 | p0 |= 0x02; | ||
949 | port->state = STATE_UNKNOWN; | ||
950 | } | ||
951 | gmidi_transmit_packet(req, p0, port->data[0], b, 0); | ||
952 | break; | ||
953 | case STATE_2PARAM_1: | ||
954 | port->data[1] = b; | ||
955 | port->state = STATE_2PARAM_2; | ||
956 | break; | ||
957 | case STATE_2PARAM_2: | ||
958 | if (port->data[0] < 0xf0) { | ||
959 | p0 |= port->data[0] >> 4; | ||
960 | port->state = STATE_2PARAM_1; | ||
961 | } else { | ||
962 | p0 |= 0x03; | ||
963 | port->state = STATE_UNKNOWN; | ||
964 | } | ||
965 | gmidi_transmit_packet(req, | ||
966 | p0, port->data[0], port->data[1], b); | ||
967 | break; | ||
968 | case STATE_SYSEX_0: | ||
969 | port->data[0] = b; | ||
970 | port->state = STATE_SYSEX_1; | ||
971 | break; | ||
972 | case STATE_SYSEX_1: | ||
973 | port->data[1] = b; | ||
974 | port->state = STATE_SYSEX_2; | ||
975 | break; | ||
976 | case STATE_SYSEX_2: | ||
977 | gmidi_transmit_packet(req, | ||
978 | p0 | 0x04, port->data[0], port->data[1], b); | ||
979 | port->state = STATE_SYSEX_0; | ||
980 | break; | ||
981 | } | ||
982 | } | ||
983 | } | ||
984 | |||
985 | static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req) | ||
986 | { | ||
987 | struct usb_ep* ep = dev->in_ep; | ||
988 | struct gmidi_in_port* port = &dev->in_port; | ||
989 | |||
990 | if (!ep) { | ||
991 | return; | ||
992 | } | ||
993 | if (!req) { | ||
994 | req = alloc_ep_req(ep, buflen); | ||
995 | } | ||
996 | if (!req) { | ||
997 | ERROR(dev, "gmidi_transmit: alloc_ep_request failed\n"); | ||
998 | return; | ||
999 | } | ||
1000 | req->length = 0; | ||
1001 | req->complete = gmidi_complete; | ||
1002 | |||
1003 | if (port->active) { | ||
1004 | while (req->length + 3 < buflen) { | ||
1005 | uint8_t b; | ||
1006 | if (snd_rawmidi_transmit(dev->in_substream, &b, 1) | ||
1007 | != 1) | ||
1008 | { | ||
1009 | port->active = 0; | ||
1010 | break; | ||
1011 | } | ||
1012 | gmidi_transmit_byte(req, port, b); | ||
1013 | } | ||
1014 | } | ||
1015 | if (req->length > 0) { | ||
1016 | usb_ep_queue(ep, req, GFP_ATOMIC); | ||
1017 | } else { | ||
1018 | free_ep_req(ep, req); | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | static void gmidi_in_tasklet(unsigned long data) | ||
1023 | { | ||
1024 | struct gmidi_device* dev = (struct gmidi_device*)data; | ||
1025 | |||
1026 | gmidi_transmit(dev, NULL); | ||
1027 | } | ||
1028 | |||
1029 | static int gmidi_in_open(struct snd_rawmidi_substream *substream) | ||
1030 | { | ||
1031 | struct gmidi_device* dev = substream->rmidi->private_data; | ||
1032 | |||
1033 | VDBG(dev, "gmidi_in_open\n"); | ||
1034 | dev->in_substream = substream; | ||
1035 | dev->in_port.state = STATE_UNKNOWN; | ||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | static int gmidi_in_close(struct snd_rawmidi_substream *substream) | ||
1040 | { | ||
1041 | VDBG(dev, "gmidi_in_close\n"); | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) | ||
1046 | { | ||
1047 | struct gmidi_device* dev = substream->rmidi->private_data; | ||
1048 | |||
1049 | VDBG(dev, "gmidi_in_trigger %d\n", up); | ||
1050 | dev->in_port.active = up; | ||
1051 | if (up) { | ||
1052 | tasklet_hi_schedule(&dev->tasklet); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | static int gmidi_out_open(struct snd_rawmidi_substream *substream) | ||
1057 | { | ||
1058 | struct gmidi_device* dev = substream->rmidi->private_data; | ||
1059 | |||
1060 | VDBG(dev, "gmidi_out_open\n"); | ||
1061 | dev->out_substream = substream; | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | static int gmidi_out_close(struct snd_rawmidi_substream *substream) | ||
1066 | { | ||
1067 | VDBG(dev, "gmidi_out_close\n"); | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up) | ||
1072 | { | ||
1073 | struct gmidi_device* dev = substream->rmidi->private_data; | ||
1074 | |||
1075 | VDBG(dev, "gmidi_out_trigger %d\n", up); | ||
1076 | if (up) { | ||
1077 | set_bit(substream->number, &dev->out_triggered); | ||
1078 | } else { | ||
1079 | clear_bit(substream->number, &dev->out_triggered); | ||
1080 | } | ||
1081 | } | ||
1082 | |||
1083 | static struct snd_rawmidi_ops gmidi_in_ops = { | ||
1084 | .open = gmidi_in_open, | ||
1085 | .close = gmidi_in_close, | ||
1086 | .trigger = gmidi_in_trigger, | ||
1087 | }; | ||
1088 | |||
1089 | static struct snd_rawmidi_ops gmidi_out_ops = { | ||
1090 | .open = gmidi_out_open, | ||
1091 | .close = gmidi_out_close, | ||
1092 | .trigger = gmidi_out_trigger | ||
1093 | }; | ||
1094 | |||
1095 | /* register as a sound "card" */ | ||
1096 | static int gmidi_register_card(struct gmidi_device *dev) | ||
1097 | { | ||
1098 | struct snd_card *card; | ||
1099 | struct snd_rawmidi *rmidi; | ||
1100 | int err; | ||
1101 | int out_ports = 1; | ||
1102 | int in_ports = 1; | ||
1103 | static struct snd_device_ops ops = { | ||
1104 | .dev_free = gmidi_snd_free, | ||
1105 | }; | ||
1106 | |||
1107 | card = snd_card_new(index, id, THIS_MODULE, 0); | ||
1108 | if (!card) { | ||
1109 | ERROR(dev, "snd_card_new failed\n"); | ||
1110 | err = -ENOMEM; | ||
1111 | goto fail; | ||
1112 | } | ||
1113 | dev->card = card; | ||
1114 | |||
1115 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, dev, &ops); | ||
1116 | if (err < 0) { | ||
1117 | ERROR(dev, "snd_device_new failed: error %d\n", err); | ||
1118 | goto fail; | ||
1119 | } | ||
1120 | |||
1121 | strcpy(card->driver, longname); | ||
1122 | strcpy(card->longname, longname); | ||
1123 | strcpy(card->shortname, shortname); | ||
1124 | |||
1125 | /* Set up rawmidi */ | ||
1126 | dev->in_port.dev = dev; | ||
1127 | dev->in_port.active = 0; | ||
1128 | snd_component_add(card, "MIDI"); | ||
1129 | err = snd_rawmidi_new(card, "USB MIDI Gadget", 0, | ||
1130 | out_ports, in_ports, &rmidi); | ||
1131 | if (err < 0) { | ||
1132 | ERROR(dev, "snd_rawmidi_new failed: error %d\n", err); | ||
1133 | goto fail; | ||
1134 | } | ||
1135 | dev->rmidi = rmidi; | ||
1136 | strcpy(rmidi->name, card->shortname); | ||
1137 | rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | | ||
1138 | SNDRV_RAWMIDI_INFO_INPUT | | ||
1139 | SNDRV_RAWMIDI_INFO_DUPLEX; | ||
1140 | rmidi->private_data = dev; | ||
1141 | |||
1142 | /* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT. | ||
1143 | It's an upside-down world being a gadget. */ | ||
1144 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops); | ||
1145 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops); | ||
1146 | |||
1147 | snd_card_set_dev(card, &dev->gadget->dev); | ||
1148 | |||
1149 | /* register it - we're ready to go */ | ||
1150 | err = snd_card_register(card); | ||
1151 | if (err < 0) { | ||
1152 | ERROR(dev, "snd_card_register failed\n"); | ||
1153 | goto fail; | ||
1154 | } | ||
1155 | |||
1156 | VDBG(dev, "gmidi_register_card finished ok\n"); | ||
1157 | return 0; | ||
1158 | |||
1159 | fail: | ||
1160 | if (dev->card) { | ||
1161 | snd_card_free(dev->card); | ||
1162 | dev->card = NULL; | ||
1163 | } | ||
1164 | return err; | ||
1165 | } | ||
1166 | |||
1167 | /* | ||
1168 | * Creates an output endpoint, and initializes output ports. | ||
1169 | */ | ||
1170 | static int __devinit gmidi_bind(struct usb_gadget *gadget) | ||
1171 | { | ||
1172 | struct gmidi_device *dev; | ||
1173 | struct usb_ep *in_ep, *out_ep; | ||
1174 | int gcnum, err = 0; | ||
1175 | |||
1176 | /* support optional vendor/distro customization */ | ||
1177 | if (idVendor) { | ||
1178 | if (!idProduct) { | ||
1179 | printk(KERN_ERR "idVendor needs idProduct!\n"); | ||
1180 | return -ENODEV; | ||
1181 | } | ||
1182 | device_desc.idVendor = cpu_to_le16(idVendor); | ||
1183 | device_desc.idProduct = cpu_to_le16(idProduct); | ||
1184 | if (bcdDevice) { | ||
1185 | device_desc.bcdDevice = cpu_to_le16(bcdDevice); | ||
1186 | } | ||
1187 | } | ||
1188 | if (iManufacturer) { | ||
1189 | strlcpy(manufacturer, iManufacturer, sizeof(manufacturer)); | ||
1190 | } else { | ||
1191 | snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", | ||
1192 | system_utsname.sysname, system_utsname.release, | ||
1193 | gadget->name); | ||
1194 | } | ||
1195 | if (iProduct) { | ||
1196 | strlcpy(product_desc, iProduct, sizeof(product_desc)); | ||
1197 | } | ||
1198 | if (iSerialNumber) { | ||
1199 | device_desc.iSerialNumber = STRING_SERIAL, | ||
1200 | strlcpy(serial_number, iSerialNumber, sizeof(serial_number)); | ||
1201 | } | ||
1202 | |||
1203 | /* Bulk-only drivers like this one SHOULD be able to | ||
1204 | * autoconfigure on any sane usb controller driver, | ||
1205 | * but there may also be important quirks to address. | ||
1206 | */ | ||
1207 | usb_ep_autoconfig_reset(gadget); | ||
1208 | in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc); | ||
1209 | if (!in_ep) { | ||
1210 | autoconf_fail: | ||
1211 | printk(KERN_ERR "%s: can't autoconfigure on %s\n", | ||
1212 | shortname, gadget->name); | ||
1213 | return -ENODEV; | ||
1214 | } | ||
1215 | EP_IN_NAME = in_ep->name; | ||
1216 | in_ep->driver_data = in_ep; /* claim */ | ||
1217 | |||
1218 | out_ep = usb_ep_autoconfig(gadget, &bulk_out_desc); | ||
1219 | if (!out_ep) { | ||
1220 | goto autoconf_fail; | ||
1221 | } | ||
1222 | EP_OUT_NAME = out_ep->name; | ||
1223 | out_ep->driver_data = out_ep; /* claim */ | ||
1224 | |||
1225 | gcnum = usb_gadget_controller_number(gadget); | ||
1226 | if (gcnum >= 0) { | ||
1227 | device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); | ||
1228 | } else { | ||
1229 | /* gmidi is so simple (no altsettings) that | ||
1230 | * it SHOULD NOT have problems with bulk-capable hardware. | ||
1231 | * so warn about unrecognized controllers, don't panic. | ||
1232 | */ | ||
1233 | printk(KERN_WARNING "%s: controller '%s' not recognized\n", | ||
1234 | shortname, gadget->name); | ||
1235 | device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); | ||
1236 | } | ||
1237 | |||
1238 | |||
1239 | /* ok, we made sense of the hardware ... */ | ||
1240 | dev = kzalloc(sizeof(*dev), SLAB_KERNEL); | ||
1241 | if (!dev) { | ||
1242 | return -ENOMEM; | ||
1243 | } | ||
1244 | spin_lock_init(&dev->lock); | ||
1245 | dev->gadget = gadget; | ||
1246 | dev->in_ep = in_ep; | ||
1247 | dev->out_ep = out_ep; | ||
1248 | set_gadget_data(gadget, dev); | ||
1249 | tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev); | ||
1250 | |||
1251 | /* preallocate control response and buffer */ | ||
1252 | dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); | ||
1253 | if (!dev->req) { | ||
1254 | err = -ENOMEM; | ||
1255 | goto fail; | ||
1256 | } | ||
1257 | dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ, | ||
1258 | &dev->req->dma, GFP_KERNEL); | ||
1259 | if (!dev->req->buf) { | ||
1260 | err = -ENOMEM; | ||
1261 | goto fail; | ||
1262 | } | ||
1263 | |||
1264 | dev->req->complete = gmidi_setup_complete; | ||
1265 | |||
1266 | device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; | ||
1267 | |||
1268 | gadget->ep0->driver_data = dev; | ||
1269 | |||
1270 | INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname); | ||
1271 | INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, | ||
1272 | EP_OUT_NAME, EP_IN_NAME); | ||
1273 | |||
1274 | /* register as an ALSA sound card */ | ||
1275 | err = gmidi_register_card(dev); | ||
1276 | if (err < 0) { | ||
1277 | goto fail; | ||
1278 | } | ||
1279 | |||
1280 | VDBG(dev, "gmidi_bind finished ok\n"); | ||
1281 | return 0; | ||
1282 | |||
1283 | fail: | ||
1284 | gmidi_unbind(gadget); | ||
1285 | return err; | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | static void gmidi_suspend(struct usb_gadget *gadget) | ||
1290 | { | ||
1291 | struct gmidi_device *dev = get_gadget_data(gadget); | ||
1292 | |||
1293 | if (gadget->speed == USB_SPEED_UNKNOWN) { | ||
1294 | return; | ||
1295 | } | ||
1296 | |||
1297 | DBG(dev, "suspend\n"); | ||
1298 | } | ||
1299 | |||
1300 | static void gmidi_resume(struct usb_gadget *gadget) | ||
1301 | { | ||
1302 | struct gmidi_device *dev = get_gadget_data(gadget); | ||
1303 | |||
1304 | DBG(dev, "resume\n"); | ||
1305 | } | ||
1306 | |||
1307 | |||
1308 | static struct usb_gadget_driver gmidi_driver = { | ||
1309 | .speed = USB_SPEED_FULL, | ||
1310 | .function = (char *)longname, | ||
1311 | .bind = gmidi_bind, | ||
1312 | .unbind = __exit_p(gmidi_unbind), | ||
1313 | |||
1314 | .setup = gmidi_setup, | ||
1315 | .disconnect = gmidi_disconnect, | ||
1316 | |||
1317 | .suspend = gmidi_suspend, | ||
1318 | .resume = gmidi_resume, | ||
1319 | |||
1320 | .driver = { | ||
1321 | .name = (char *)shortname, | ||
1322 | .owner = THIS_MODULE, | ||
1323 | }, | ||
1324 | }; | ||
1325 | |||
1326 | static int __init gmidi_init(void) | ||
1327 | { | ||
1328 | return usb_gadget_register_driver(&gmidi_driver); | ||
1329 | } | ||
1330 | module_init(gmidi_init); | ||
1331 | |||
1332 | static void __exit gmidi_cleanup(void) | ||
1333 | { | ||
1334 | usb_gadget_unregister_driver(&gmidi_driver); | ||
1335 | } | ||
1336 | module_exit(gmidi_cleanup); | ||
1337 | |||
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 3bdc5e3ba234..4655522a08d9 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/compiler.h> | 32 | #include <linux/compiler.h> |
33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/poll.h> | ||
35 | 36 | ||
36 | #include <linux/device.h> | 37 | #include <linux/device.h> |
37 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
@@ -222,7 +223,6 @@ static void put_ep (struct ep_data *data) | |||
222 | /* needs no more cleanup */ | 223 | /* needs no more cleanup */ |
223 | BUG_ON (!list_empty (&data->epfiles)); | 224 | BUG_ON (!list_empty (&data->epfiles)); |
224 | BUG_ON (waitqueue_active (&data->wait)); | 225 | BUG_ON (waitqueue_active (&data->wait)); |
225 | BUG_ON (down_trylock (&data->lock) != 0); | ||
226 | kfree (data); | 226 | kfree (data); |
227 | } | 227 | } |
228 | 228 | ||
@@ -477,6 +477,10 @@ static int | |||
477 | ep_release (struct inode *inode, struct file *fd) | 477 | ep_release (struct inode *inode, struct file *fd) |
478 | { | 478 | { |
479 | struct ep_data *data = fd->private_data; | 479 | struct ep_data *data = fd->private_data; |
480 | int value; | ||
481 | |||
482 | if ((value = down_interruptible(&data->lock)) < 0) | ||
483 | return value; | ||
480 | 484 | ||
481 | /* clean up if this can be reopened */ | 485 | /* clean up if this can be reopened */ |
482 | if (data->state != STATE_EP_UNBOUND) { | 486 | if (data->state != STATE_EP_UNBOUND) { |
@@ -485,6 +489,7 @@ ep_release (struct inode *inode, struct file *fd) | |||
485 | data->hs_desc.bDescriptorType = 0; | 489 | data->hs_desc.bDescriptorType = 0; |
486 | usb_ep_disable(data->ep); | 490 | usb_ep_disable(data->ep); |
487 | } | 491 | } |
492 | up (&data->lock); | ||
488 | put_ep (data); | 493 | put_ep (data); |
489 | return 0; | 494 | return 0; |
490 | } | 495 | } |
@@ -709,7 +714,7 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o) | |||
709 | /*----------------------------------------------------------------------*/ | 714 | /*----------------------------------------------------------------------*/ |
710 | 715 | ||
711 | /* used after endpoint configuration */ | 716 | /* used after endpoint configuration */ |
712 | static struct file_operations ep_io_operations = { | 717 | static const struct file_operations ep_io_operations = { |
713 | .owner = THIS_MODULE, | 718 | .owner = THIS_MODULE, |
714 | .llseek = no_llseek, | 719 | .llseek = no_llseek, |
715 | 720 | ||
@@ -741,7 +746,7 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
741 | struct ep_data *data = fd->private_data; | 746 | struct ep_data *data = fd->private_data; |
742 | struct usb_ep *ep; | 747 | struct usb_ep *ep; |
743 | u32 tag; | 748 | u32 tag; |
744 | int value; | 749 | int value, length = len; |
745 | 750 | ||
746 | if ((value = down_interruptible (&data->lock)) < 0) | 751 | if ((value = down_interruptible (&data->lock)) < 0) |
747 | return value; | 752 | return value; |
@@ -792,7 +797,6 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
792 | goto fail0; | 797 | goto fail0; |
793 | } | 798 | } |
794 | } | 799 | } |
795 | value = len; | ||
796 | 800 | ||
797 | spin_lock_irq (&data->dev->lock); | 801 | spin_lock_irq (&data->dev->lock); |
798 | if (data->dev->state == STATE_DEV_UNBOUND) { | 802 | if (data->dev->state == STATE_DEV_UNBOUND) { |
@@ -822,8 +826,10 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
822 | data->name); | 826 | data->name); |
823 | data->state = STATE_EP_DEFER_ENABLE; | 827 | data->state = STATE_EP_DEFER_ENABLE; |
824 | } | 828 | } |
825 | if (value == 0) | 829 | if (value == 0) { |
826 | fd->f_op = &ep_io_operations; | 830 | fd->f_op = &ep_io_operations; |
831 | value = length; | ||
832 | } | ||
827 | gone: | 833 | gone: |
828 | spin_unlock_irq (&data->dev->lock); | 834 | spin_unlock_irq (&data->dev->lock); |
829 | if (value < 0) { | 835 | if (value < 0) { |
@@ -844,7 +850,7 @@ fail1: | |||
844 | static int | 850 | static int |
845 | ep_open (struct inode *inode, struct file *fd) | 851 | ep_open (struct inode *inode, struct file *fd) |
846 | { | 852 | { |
847 | struct ep_data *data = inode->u.generic_ip; | 853 | struct ep_data *data = inode->i_private; |
848 | int value = -EBUSY; | 854 | int value = -EBUSY; |
849 | 855 | ||
850 | if (down_interruptible (&data->lock) != 0) | 856 | if (down_interruptible (&data->lock) != 0) |
@@ -867,7 +873,7 @@ ep_open (struct inode *inode, struct file *fd) | |||
867 | } | 873 | } |
868 | 874 | ||
869 | /* used before endpoint configuration */ | 875 | /* used before endpoint configuration */ |
870 | static struct file_operations ep_config_operations = { | 876 | static const struct file_operations ep_config_operations = { |
871 | .owner = THIS_MODULE, | 877 | .owner = THIS_MODULE, |
872 | .llseek = no_llseek, | 878 | .llseek = no_llseek, |
873 | 879 | ||
@@ -1009,7 +1015,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) | |||
1009 | else { | 1015 | else { |
1010 | len = min (len, (size_t)dev->req->actual); | 1016 | len = min (len, (size_t)dev->req->actual); |
1011 | // FIXME don't call this with the spinlock held ... | 1017 | // FIXME don't call this with the spinlock held ... |
1012 | if (copy_to_user (buf, &dev->req->buf, len)) | 1018 | if (copy_to_user (buf, dev->req->buf, len)) |
1013 | retval = -EFAULT; | 1019 | retval = -EFAULT; |
1014 | clean_req (dev->gadget->ep0, dev->req); | 1020 | clean_req (dev->gadget->ep0, dev->req); |
1015 | /* NOTE userspace can't yet choose to stall */ | 1021 | /* NOTE userspace can't yet choose to stall */ |
@@ -1229,6 +1235,35 @@ dev_release (struct inode *inode, struct file *fd) | |||
1229 | return 0; | 1235 | return 0; |
1230 | } | 1236 | } |
1231 | 1237 | ||
1238 | static unsigned int | ||
1239 | ep0_poll (struct file *fd, poll_table *wait) | ||
1240 | { | ||
1241 | struct dev_data *dev = fd->private_data; | ||
1242 | int mask = 0; | ||
1243 | |||
1244 | poll_wait(fd, &dev->wait, wait); | ||
1245 | |||
1246 | spin_lock_irq (&dev->lock); | ||
1247 | |||
1248 | /* report fd mode change before acting on it */ | ||
1249 | if (dev->setup_abort) { | ||
1250 | dev->setup_abort = 0; | ||
1251 | mask = POLLHUP; | ||
1252 | goto out; | ||
1253 | } | ||
1254 | |||
1255 | if (dev->state == STATE_SETUP) { | ||
1256 | if (dev->setup_in || dev->setup_can_stall) | ||
1257 | mask = POLLOUT; | ||
1258 | } else { | ||
1259 | if (dev->ev_next != 0) | ||
1260 | mask = POLLIN; | ||
1261 | } | ||
1262 | out: | ||
1263 | spin_unlock_irq(&dev->lock); | ||
1264 | return mask; | ||
1265 | } | ||
1266 | |||
1232 | static int dev_ioctl (struct inode *inode, struct file *fd, | 1267 | static int dev_ioctl (struct inode *inode, struct file *fd, |
1233 | unsigned code, unsigned long value) | 1268 | unsigned code, unsigned long value) |
1234 | { | 1269 | { |
@@ -1241,14 +1276,14 @@ static int dev_ioctl (struct inode *inode, struct file *fd, | |||
1241 | } | 1276 | } |
1242 | 1277 | ||
1243 | /* used after device configuration */ | 1278 | /* used after device configuration */ |
1244 | static struct file_operations ep0_io_operations = { | 1279 | static const struct file_operations ep0_io_operations = { |
1245 | .owner = THIS_MODULE, | 1280 | .owner = THIS_MODULE, |
1246 | .llseek = no_llseek, | 1281 | .llseek = no_llseek, |
1247 | 1282 | ||
1248 | .read = ep0_read, | 1283 | .read = ep0_read, |
1249 | .write = ep0_write, | 1284 | .write = ep0_write, |
1250 | .fasync = ep0_fasync, | 1285 | .fasync = ep0_fasync, |
1251 | // .poll = ep0_poll, | 1286 | .poll = ep0_poll, |
1252 | .ioctl = dev_ioctl, | 1287 | .ioctl = dev_ioctl, |
1253 | .release = dev_release, | 1288 | .release = dev_release, |
1254 | }; | 1289 | }; |
@@ -1696,16 +1731,17 @@ gadgetfs_disconnect (struct usb_gadget *gadget) | |||
1696 | { | 1731 | { |
1697 | struct dev_data *dev = get_gadget_data (gadget); | 1732 | struct dev_data *dev = get_gadget_data (gadget); |
1698 | 1733 | ||
1734 | spin_lock (&dev->lock); | ||
1699 | if (dev->state == STATE_UNCONNECTED) { | 1735 | if (dev->state == STATE_UNCONNECTED) { |
1700 | DBG (dev, "already unconnected\n"); | 1736 | DBG (dev, "already unconnected\n"); |
1701 | return; | 1737 | goto exit; |
1702 | } | 1738 | } |
1703 | dev->state = STATE_UNCONNECTED; | 1739 | dev->state = STATE_UNCONNECTED; |
1704 | 1740 | ||
1705 | INFO (dev, "disconnected\n"); | 1741 | INFO (dev, "disconnected\n"); |
1706 | spin_lock (&dev->lock); | ||
1707 | next_event (dev, GADGETFS_DISCONNECT); | 1742 | next_event (dev, GADGETFS_DISCONNECT); |
1708 | ep0_readable (dev); | 1743 | ep0_readable (dev); |
1744 | exit: | ||
1709 | spin_unlock (&dev->lock); | 1745 | spin_unlock (&dev->lock); |
1710 | } | 1746 | } |
1711 | 1747 | ||
@@ -1909,7 +1945,7 @@ fail: | |||
1909 | static int | 1945 | static int |
1910 | dev_open (struct inode *inode, struct file *fd) | 1946 | dev_open (struct inode *inode, struct file *fd) |
1911 | { | 1947 | { |
1912 | struct dev_data *dev = inode->u.generic_ip; | 1948 | struct dev_data *dev = inode->i_private; |
1913 | int value = -EBUSY; | 1949 | int value = -EBUSY; |
1914 | 1950 | ||
1915 | if (dev->state == STATE_DEV_DISABLED) { | 1951 | if (dev->state == STATE_DEV_DISABLED) { |
@@ -1922,7 +1958,7 @@ dev_open (struct inode *inode, struct file *fd) | |||
1922 | return value; | 1958 | return value; |
1923 | } | 1959 | } |
1924 | 1960 | ||
1925 | static struct file_operations dev_init_operations = { | 1961 | static const struct file_operations dev_init_operations = { |
1926 | .owner = THIS_MODULE, | 1962 | .owner = THIS_MODULE, |
1927 | .llseek = no_llseek, | 1963 | .llseek = no_llseek, |
1928 | 1964 | ||
@@ -1966,11 +2002,10 @@ gadgetfs_make_inode (struct super_block *sb, | |||
1966 | inode->i_mode = mode; | 2002 | inode->i_mode = mode; |
1967 | inode->i_uid = default_uid; | 2003 | inode->i_uid = default_uid; |
1968 | inode->i_gid = default_gid; | 2004 | inode->i_gid = default_gid; |
1969 | inode->i_blksize = PAGE_CACHE_SIZE; | ||
1970 | inode->i_blocks = 0; | 2005 | inode->i_blocks = 0; |
1971 | inode->i_atime = inode->i_mtime = inode->i_ctime | 2006 | inode->i_atime = inode->i_mtime = inode->i_ctime |
1972 | = CURRENT_TIME; | 2007 | = CURRENT_TIME; |
1973 | inode->u.generic_ip = data; | 2008 | inode->i_private = data; |
1974 | inode->i_fop = fops; | 2009 | inode->i_fop = fops; |
1975 | } | 2010 | } |
1976 | return inode; | 2011 | return inode; |
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 09243239d948..3bda37f9a35f 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Driver for the PLX NET2280 USB device controller. | 2 | * Driver for the PLX NET2280 USB device controller. |
3 | * Specs and errata are available from <http://www.plxtech.com>. | 3 | * Specs and errata are available from <http://www.plxtech.com>. |
4 | * | 4 | * |
5 | * PLX Technology Inc. (formerly NetChip Technology) supported the | 5 | * PLX Technology Inc. (formerly NetChip Technology) supported the |
6 | * development of this driver. | 6 | * development of this driver. |
7 | * | 7 | * |
8 | * | 8 | * |
@@ -26,7 +26,8 @@ | |||
26 | * Copyright (C) 2003 David Brownell | 26 | * Copyright (C) 2003 David Brownell |
27 | * Copyright (C) 2003-2005 PLX Technology, Inc. | 27 | * Copyright (C) 2003-2005 PLX Technology, Inc. |
28 | * | 28 | * |
29 | * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip | 29 | * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility |
30 | * with 2282 chip | ||
30 | * | 31 | * |
31 | * This program is free software; you can redistribute it and/or modify | 32 | * This program is free software; you can redistribute it and/or modify |
32 | * it under the terms of the GNU General Public License as published by | 33 | * it under the terms of the GNU General Public License as published by |
@@ -85,7 +86,7 @@ static const char driver_name [] = "net2280"; | |||
85 | static const char driver_desc [] = DRIVER_DESC; | 86 | static const char driver_desc [] = DRIVER_DESC; |
86 | 87 | ||
87 | static const char ep0name [] = "ep0"; | 88 | static const char ep0name [] = "ep0"; |
88 | static const char *ep_name [] = { | 89 | static const char *const ep_name [] = { |
89 | ep0name, | 90 | ep0name, |
90 | "ep-a", "ep-b", "ep-c", "ep-d", | 91 | "ep-a", "ep-b", "ep-c", "ep-d", |
91 | "ep-e", "ep-f", | 92 | "ep-e", "ep-f", |
@@ -225,7 +226,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) | |||
225 | if (!ep->is_in) | 226 | if (!ep->is_in) |
226 | writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp); | 227 | writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp); |
227 | else if (dev->pdev->device != 0x2280) { | 228 | else if (dev->pdev->device != 0x2280) { |
228 | /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */ | 229 | /* Added for 2282, Don't use nak packets on an in endpoint, |
230 | * this was ignored on 2280 | ||
231 | */ | ||
229 | writel ((1 << CLEAR_NAK_OUT_PACKETS) | 232 | writel ((1 << CLEAR_NAK_OUT_PACKETS) |
230 | | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp); | 233 | | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp); |
231 | } | 234 | } |
@@ -288,7 +291,7 @@ static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec) | |||
288 | return -ETIMEDOUT; | 291 | return -ETIMEDOUT; |
289 | } | 292 | } |
290 | 293 | ||
291 | static struct usb_ep_ops net2280_ep_ops; | 294 | static const struct usb_ep_ops net2280_ep_ops; |
292 | 295 | ||
293 | static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep) | 296 | static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep) |
294 | { | 297 | { |
@@ -449,34 +452,15 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req) | |||
449 | 452 | ||
450 | /*-------------------------------------------------------------------------*/ | 453 | /*-------------------------------------------------------------------------*/ |
451 | 454 | ||
452 | #undef USE_KMALLOC | 455 | /* |
453 | 456 | * dma-coherent memory allocation (for dma-capable endpoints) | |
454 | /* many common platforms have dma-coherent caches, which means that it's | ||
455 | * safe to use kmalloc() memory for all i/o buffers without using any | ||
456 | * cache flushing calls. (unless you're trying to share cache lines | ||
457 | * between dma and non-dma activities, which is a slow idea in any case.) | ||
458 | * | 457 | * |
459 | * other platforms need more care, with 2.5 having a moderately general | 458 | * NOTE: the dma_*_coherent() API calls suck. Most implementations are |
460 | * solution (which falls down for allocations smaller than one page) | 459 | * (a) page-oriented, so small buffers lose big; and (b) asymmetric with |
461 | * that improves significantly on the 2.4 PCI allocators by removing | 460 | * respect to calls with irqs disabled: alloc is safe, free is not. |
462 | * the restriction that memory never be freed in_interrupt(). | 461 | * We currently work around (b), but not (a). |
463 | */ | 462 | */ |
464 | #if defined(CONFIG_X86) | ||
465 | #define USE_KMALLOC | ||
466 | |||
467 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) | ||
468 | #define USE_KMALLOC | ||
469 | 463 | ||
470 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT) | ||
471 | #define USE_KMALLOC | ||
472 | |||
473 | /* FIXME there are other cases, including an x86-64 one ... */ | ||
474 | #endif | ||
475 | |||
476 | /* allocating buffers this way eliminates dma mapping overhead, which | ||
477 | * on some platforms will mean eliminating a per-io buffer copy. with | ||
478 | * some kinds of system caches, further tweaks may still be needed. | ||
479 | */ | ||
480 | static void * | 464 | static void * |
481 | net2280_alloc_buffer ( | 465 | net2280_alloc_buffer ( |
482 | struct usb_ep *_ep, | 466 | struct usb_ep *_ep, |
@@ -493,43 +477,71 @@ net2280_alloc_buffer ( | |||
493 | return NULL; | 477 | return NULL; |
494 | *dma = DMA_ADDR_INVALID; | 478 | *dma = DMA_ADDR_INVALID; |
495 | 479 | ||
496 | #if defined(USE_KMALLOC) | 480 | if (ep->dma) |
497 | retval = kmalloc(bytes, gfp_flags); | ||
498 | if (retval) | ||
499 | *dma = virt_to_phys(retval); | ||
500 | #else | ||
501 | if (ep->dma) { | ||
502 | /* the main problem with this call is that it wastes memory | ||
503 | * on typical 1/N page allocations: it allocates 1-N pages. | ||
504 | */ | ||
505 | #warning Using dma_alloc_coherent even with buffers smaller than a page. | ||
506 | retval = dma_alloc_coherent(&ep->dev->pdev->dev, | 481 | retval = dma_alloc_coherent(&ep->dev->pdev->dev, |
507 | bytes, dma, gfp_flags); | 482 | bytes, dma, gfp_flags); |
508 | } else | 483 | else |
509 | retval = kmalloc(bytes, gfp_flags); | 484 | retval = kmalloc(bytes, gfp_flags); |
510 | #endif | ||
511 | return retval; | 485 | return retval; |
512 | } | 486 | } |
513 | 487 | ||
488 | static DEFINE_SPINLOCK(buflock); | ||
489 | static LIST_HEAD(buffers); | ||
490 | |||
491 | struct free_record { | ||
492 | struct list_head list; | ||
493 | struct device *dev; | ||
494 | unsigned bytes; | ||
495 | dma_addr_t dma; | ||
496 | }; | ||
497 | |||
498 | static void do_free(unsigned long ignored) | ||
499 | { | ||
500 | spin_lock_irq(&buflock); | ||
501 | while (!list_empty(&buffers)) { | ||
502 | struct free_record *buf; | ||
503 | |||
504 | buf = list_entry(buffers.next, struct free_record, list); | ||
505 | list_del(&buf->list); | ||
506 | spin_unlock_irq(&buflock); | ||
507 | |||
508 | dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma); | ||
509 | |||
510 | spin_lock_irq(&buflock); | ||
511 | } | ||
512 | spin_unlock_irq(&buflock); | ||
513 | } | ||
514 | |||
515 | static DECLARE_TASKLET(deferred_free, do_free, 0); | ||
516 | |||
514 | static void | 517 | static void |
515 | net2280_free_buffer ( | 518 | net2280_free_buffer ( |
516 | struct usb_ep *_ep, | 519 | struct usb_ep *_ep, |
517 | void *buf, | 520 | void *address, |
518 | dma_addr_t dma, | 521 | dma_addr_t dma, |
519 | unsigned bytes | 522 | unsigned bytes |
520 | ) { | 523 | ) { |
521 | /* free memory into the right allocator */ | 524 | /* free memory into the right allocator */ |
522 | #ifndef USE_KMALLOC | ||
523 | if (dma != DMA_ADDR_INVALID) { | 525 | if (dma != DMA_ADDR_INVALID) { |
524 | struct net2280_ep *ep; | 526 | struct net2280_ep *ep; |
527 | struct free_record *buf = address; | ||
528 | unsigned long flags; | ||
525 | 529 | ||
526 | ep = container_of(_ep, struct net2280_ep, ep); | 530 | ep = container_of(_ep, struct net2280_ep, ep); |
527 | if (!_ep) | 531 | if (!_ep) |
528 | return; | 532 | return; |
529 | dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); | 533 | |
534 | ep = container_of (_ep, struct net2280_ep, ep); | ||
535 | buf->dev = &ep->dev->pdev->dev; | ||
536 | buf->bytes = bytes; | ||
537 | buf->dma = dma; | ||
538 | |||
539 | spin_lock_irqsave(&buflock, flags); | ||
540 | list_add_tail(&buf->list, &buffers); | ||
541 | tasklet_schedule(&deferred_free); | ||
542 | spin_unlock_irqrestore(&buflock, flags); | ||
530 | } else | 543 | } else |
531 | #endif | 544 | kfree (address); |
532 | kfree (buf); | ||
533 | } | 545 | } |
534 | 546 | ||
535 | /*-------------------------------------------------------------------------*/ | 547 | /*-------------------------------------------------------------------------*/ |
@@ -737,7 +749,8 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) | |||
737 | */ | 749 | */ |
738 | if (ep->is_in) | 750 | if (ep->is_in) |
739 | dmacount |= (1 << DMA_DIRECTION); | 751 | dmacount |= (1 << DMA_DIRECTION); |
740 | if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280) | 752 | if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) |
753 | || ep->dev->pdev->device != 0x2280) | ||
741 | dmacount |= (1 << END_OF_CHAIN); | 754 | dmacount |= (1 << END_OF_CHAIN); |
742 | 755 | ||
743 | req->valid = valid; | 756 | req->valid = valid; |
@@ -812,7 +825,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) | |||
812 | 825 | ||
813 | /* previous OUT packet might have been short */ | 826 | /* previous OUT packet might have been short */ |
814 | if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat)) | 827 | if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat)) |
815 | & (1 << NAK_OUT_PACKETS)) != 0) { | 828 | & (1 << NAK_OUT_PACKETS)) != 0) { |
816 | writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT), | 829 | writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT), |
817 | &ep->regs->ep_stat); | 830 | &ep->regs->ep_stat); |
818 | 831 | ||
@@ -1373,7 +1386,7 @@ net2280_fifo_flush (struct usb_ep *_ep) | |||
1373 | (void) readl (&ep->regs->ep_rsp); | 1386 | (void) readl (&ep->regs->ep_rsp); |
1374 | } | 1387 | } |
1375 | 1388 | ||
1376 | static struct usb_ep_ops net2280_ep_ops = { | 1389 | static const struct usb_ep_ops net2280_ep_ops = { |
1377 | .enable = net2280_enable, | 1390 | .enable = net2280_enable, |
1378 | .disable = net2280_disable, | 1391 | .disable = net2280_disable, |
1379 | 1392 | ||
@@ -1631,7 +1644,7 @@ show_registers (struct device *_dev, struct device_attribute *attr, char *buf) | |||
1631 | } | 1644 | } |
1632 | 1645 | ||
1633 | /* Indexed Registers */ | 1646 | /* Indexed Registers */ |
1634 | // none yet | 1647 | // none yet |
1635 | 1648 | ||
1636 | /* Statistics */ | 1649 | /* Statistics */ |
1637 | t = scnprintf (next, size, "\nirqs: "); | 1650 | t = scnprintf (next, size, "\nirqs: "); |
@@ -1691,11 +1704,11 @@ show_queues (struct device *_dev, struct device_attribute *attr, char *buf) | |||
1691 | ({ char *val; | 1704 | ({ char *val; |
1692 | switch (d->bmAttributes & 0x03) { | 1705 | switch (d->bmAttributes & 0x03) { |
1693 | case USB_ENDPOINT_XFER_BULK: | 1706 | case USB_ENDPOINT_XFER_BULK: |
1694 | val = "bulk"; break; | 1707 | val = "bulk"; break; |
1695 | case USB_ENDPOINT_XFER_INT: | 1708 | case USB_ENDPOINT_XFER_INT: |
1696 | val = "intr"; break; | 1709 | val = "intr"; break; |
1697 | default: | 1710 | default: |
1698 | val = "iso"; break; | 1711 | val = "iso"; break; |
1699 | }; val; }), | 1712 | }; val; }), |
1700 | le16_to_cpu (d->wMaxPacketSize) & 0x1fff, | 1713 | le16_to_cpu (d->wMaxPacketSize) & 0x1fff, |
1701 | ep->dma ? "dma" : "pio", ep->fifo_size | 1714 | ep->dma ? "dma" : "pio", ep->fifo_size |
@@ -1808,8 +1821,8 @@ extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); | |||
1808 | * net2280_set_fifo_mode - change allocation of fifo buffers | 1821 | * net2280_set_fifo_mode - change allocation of fifo buffers |
1809 | * @gadget: access to the net2280 device that will be updated | 1822 | * @gadget: access to the net2280 device that will be updated |
1810 | * @mode: 0 for default, four 1kB buffers (ep-a through ep-d); | 1823 | * @mode: 0 for default, four 1kB buffers (ep-a through ep-d); |
1811 | * 1 for two 2kB buffers (ep-a and ep-b only); | 1824 | * 1 for two 2kB buffers (ep-a and ep-b only); |
1812 | * 2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c). | 1825 | * 2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c). |
1813 | * | 1826 | * |
1814 | * returns zero on success, else negative errno. when this succeeds, | 1827 | * returns zero on success, else negative errno. when this succeeds, |
1815 | * the contents of gadget->ep_list may have changed. | 1828 | * the contents of gadget->ep_list may have changed. |
@@ -2241,7 +2254,8 @@ static void handle_ep_small (struct net2280_ep *ep) | |||
2241 | req->td->dmacount = 0; | 2254 | req->td->dmacount = 0; |
2242 | t = readl (&ep->regs->ep_avail); | 2255 | t = readl (&ep->regs->ep_avail); |
2243 | dma_done (ep, req, count, | 2256 | dma_done (ep, req, count, |
2244 | (ep->out_overflow || t) ? -EOVERFLOW : 0); | 2257 | (ep->out_overflow || t) |
2258 | ? -EOVERFLOW : 0); | ||
2245 | } | 2259 | } |
2246 | 2260 | ||
2247 | /* also flush to prevent erratum 0106 trouble */ | 2261 | /* also flush to prevent erratum 0106 trouble */ |
@@ -2411,7 +2425,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2411 | , &ep->regs->ep_stat); | 2425 | , &ep->regs->ep_stat); |
2412 | u.raw [0] = readl (&dev->usb->setup0123); | 2426 | u.raw [0] = readl (&dev->usb->setup0123); |
2413 | u.raw [1] = readl (&dev->usb->setup4567); | 2427 | u.raw [1] = readl (&dev->usb->setup4567); |
2414 | 2428 | ||
2415 | cpu_to_le32s (&u.raw [0]); | 2429 | cpu_to_le32s (&u.raw [0]); |
2416 | cpu_to_le32s (&u.raw [1]); | 2430 | cpu_to_le32s (&u.raw [1]); |
2417 | 2431 | ||
@@ -2578,14 +2592,16 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) | |||
2578 | 2592 | ||
2579 | /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set. | 2593 | /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set. |
2580 | * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and | 2594 | * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and |
2581 | * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT | 2595 | * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT |
2582 | * only indicates a change in the reset state). | 2596 | * only indicates a change in the reset state). |
2583 | */ | 2597 | */ |
2584 | if (stat & tmp) { | 2598 | if (stat & tmp) { |
2585 | writel (tmp, &dev->regs->irqstat1); | 2599 | writel (tmp, &dev->regs->irqstat1); |
2586 | if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && | 2600 | if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) |
2587 | ((readl (&dev->usb->usbstat) & mask) == 0)) | 2601 | && ((readl (&dev->usb->usbstat) & mask) |
2588 | || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) | 2602 | == 0)) |
2603 | || ((readl (&dev->usb->usbctl) | ||
2604 | & (1 << VBUS_PIN)) == 0) | ||
2589 | ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) { | 2605 | ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) { |
2590 | DEBUG (dev, "disconnect %s\n", | 2606 | DEBUG (dev, "disconnect %s\n", |
2591 | dev->driver->driver.name); | 2607 | dev->driver->driver.name); |
@@ -2852,7 +2868,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) | |||
2852 | 2868 | ||
2853 | /* now all the pci goodies ... */ | 2869 | /* now all the pci goodies ... */ |
2854 | if (pci_enable_device (pdev) < 0) { | 2870 | if (pci_enable_device (pdev) < 0) { |
2855 | retval = -ENODEV; | 2871 | retval = -ENODEV; |
2856 | goto done; | 2872 | goto done; |
2857 | } | 2873 | } |
2858 | dev->enabled = 1; | 2874 | dev->enabled = 1; |
@@ -2870,6 +2886,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) | |||
2870 | } | 2886 | } |
2871 | dev->region = 1; | 2887 | dev->region = 1; |
2872 | 2888 | ||
2889 | /* FIXME provide firmware download interface to put | ||
2890 | * 8051 code into the chip, e.g. to turn on PCI PM. | ||
2891 | */ | ||
2892 | |||
2873 | base = ioremap_nocache (resource, len); | 2893 | base = ioremap_nocache (resource, len); |
2874 | if (base == NULL) { | 2894 | if (base == NULL) { |
2875 | DEBUG (dev, "can't map memory\n"); | 2895 | DEBUG (dev, "can't map memory\n"); |
@@ -2984,16 +3004,16 @@ static void net2280_shutdown (struct pci_dev *pdev) | |||
2984 | 3004 | ||
2985 | /*-------------------------------------------------------------------------*/ | 3005 | /*-------------------------------------------------------------------------*/ |
2986 | 3006 | ||
2987 | static struct pci_device_id pci_ids [] = { { | 3007 | static const struct pci_device_id pci_ids [] = { { |
2988 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | 3008 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), |
2989 | .class_mask = ~0, | 3009 | .class_mask = ~0, |
2990 | .vendor = 0x17cc, | 3010 | .vendor = 0x17cc, |
2991 | .device = 0x2280, | 3011 | .device = 0x2280, |
2992 | .subvendor = PCI_ANY_ID, | 3012 | .subvendor = PCI_ANY_ID, |
2993 | .subdevice = PCI_ANY_ID, | 3013 | .subdevice = PCI_ANY_ID, |
2994 | }, { | 3014 | }, { |
2995 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | 3015 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), |
2996 | .class_mask = ~0, | 3016 | .class_mask = ~0, |
2997 | .vendor = 0x17cc, | 3017 | .vendor = 0x17cc, |
2998 | .device = 0x2282, | 3018 | .device = 0x2282, |
2999 | .subvendor = PCI_ANY_ID, | 3019 | .subvendor = PCI_ANY_ID, |
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 2de9748ee673..0a64504c2545 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
41 | #include <linux/usb_ch9.h> | 41 | #include <linux/usb_ch9.h> |
42 | #include <linux/usb_gadget.h> | 42 | #include <linux/usb_gadget.h> |
43 | #include <linux/usb_otg.h> | 43 | #include <linux/usb/otg.h> |
44 | #include <linux/dma-mapping.h> | 44 | #include <linux/dma-mapping.h> |
45 | 45 | ||
46 | #include <asm/byteorder.h> | 46 | #include <asm/byteorder.h> |
@@ -2437,7 +2437,7 @@ static int proc_udc_open(struct inode *inode, struct file *file) | |||
2437 | return single_open(file, proc_udc_show, NULL); | 2437 | return single_open(file, proc_udc_show, NULL); |
2438 | } | 2438 | } |
2439 | 2439 | ||
2440 | static struct file_operations proc_ops = { | 2440 | static const struct file_operations proc_ops = { |
2441 | .open = proc_udc_open, | 2441 | .open = proc_udc_open, |
2442 | .read = seq_read, | 2442 | .read = seq_read, |
2443 | .llseek = seq_lseek, | 2443 | .llseek = seq_lseek, |
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index fff027d30a09..f1adcf8b2023 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -150,6 +150,39 @@ MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode"); | |||
150 | static void pxa2xx_ep_fifo_flush (struct usb_ep *ep); | 150 | static void pxa2xx_ep_fifo_flush (struct usb_ep *ep); |
151 | static void nuke (struct pxa2xx_ep *, int status); | 151 | static void nuke (struct pxa2xx_ep *, int status); |
152 | 152 | ||
153 | /* one GPIO should be used to detect VBUS from the host */ | ||
154 | static int is_vbus_present(void) | ||
155 | { | ||
156 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | ||
157 | |||
158 | if (mach->gpio_vbus) | ||
159 | return pxa_gpio_get(mach->gpio_vbus); | ||
160 | if (mach->udc_is_connected) | ||
161 | return mach->udc_is_connected(); | ||
162 | return 1; | ||
163 | } | ||
164 | |||
165 | /* one GPIO should control a D+ pullup, so host sees this device (or not) */ | ||
166 | static void pullup_off(void) | ||
167 | { | ||
168 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | ||
169 | |||
170 | if (mach->gpio_pullup) | ||
171 | pxa_gpio_set(mach->gpio_pullup, 0); | ||
172 | else if (mach->udc_command) | ||
173 | mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); | ||
174 | } | ||
175 | |||
176 | static void pullup_on(void) | ||
177 | { | ||
178 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | ||
179 | |||
180 | if (mach->gpio_pullup) | ||
181 | pxa_gpio_set(mach->gpio_pullup, 1); | ||
182 | else if (mach->udc_command) | ||
183 | mach->udc_command(PXA2XX_UDC_CMD_CONNECT); | ||
184 | } | ||
185 | |||
153 | static void pio_irq_enable(int bEndpointAddress) | 186 | static void pio_irq_enable(int bEndpointAddress) |
154 | { | 187 | { |
155 | bEndpointAddress &= 0xf; | 188 | bEndpointAddress &= 0xf; |
@@ -1721,6 +1754,16 @@ lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r) | |||
1721 | 1754 | ||
1722 | #endif | 1755 | #endif |
1723 | 1756 | ||
1757 | static irqreturn_t | ||
1758 | udc_vbus_irq(int irq, void *_dev, struct pt_regs *r) | ||
1759 | { | ||
1760 | struct pxa2xx_udc *dev = _dev; | ||
1761 | int vbus = pxa_gpio_get(dev->mach->gpio_vbus); | ||
1762 | |||
1763 | pxa2xx_udc_vbus_session(&dev->gadget, vbus); | ||
1764 | return IRQ_HANDLED; | ||
1765 | } | ||
1766 | |||
1724 | 1767 | ||
1725 | /*-------------------------------------------------------------------------*/ | 1768 | /*-------------------------------------------------------------------------*/ |
1726 | 1769 | ||
@@ -2438,7 +2481,7 @@ static struct pxa2xx_udc memory = { | |||
2438 | static int __init pxa2xx_udc_probe(struct platform_device *pdev) | 2481 | static int __init pxa2xx_udc_probe(struct platform_device *pdev) |
2439 | { | 2482 | { |
2440 | struct pxa2xx_udc *dev = &memory; | 2483 | struct pxa2xx_udc *dev = &memory; |
2441 | int retval, out_dma = 1; | 2484 | int retval, out_dma = 1, vbus_irq; |
2442 | u32 chiprev; | 2485 | u32 chiprev; |
2443 | 2486 | ||
2444 | /* insist on Intel/ARM/XScale */ | 2487 | /* insist on Intel/ARM/XScale */ |
@@ -2502,6 +2545,16 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
2502 | /* other non-static parts of init */ | 2545 | /* other non-static parts of init */ |
2503 | dev->dev = &pdev->dev; | 2546 | dev->dev = &pdev->dev; |
2504 | dev->mach = pdev->dev.platform_data; | 2547 | dev->mach = pdev->dev.platform_data; |
2548 | if (dev->mach->gpio_vbus) { | ||
2549 | vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR); | ||
2550 | pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR) | ||
2551 | | GPIO_IN); | ||
2552 | set_irq_type(vbus_irq, IRQT_BOTHEDGE); | ||
2553 | } else | ||
2554 | vbus_irq = 0; | ||
2555 | if (dev->mach->gpio_pullup) | ||
2556 | pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR) | ||
2557 | | GPIO_OUT | GPIO_DFLT_LOW); | ||
2505 | 2558 | ||
2506 | init_timer(&dev->timer); | 2559 | init_timer(&dev->timer); |
2507 | dev->timer.function = udc_watchdog; | 2560 | dev->timer.function = udc_watchdog; |
@@ -2557,8 +2610,19 @@ lubbock_fail0: | |||
2557 | HEX_DISPLAY(dev->stats.irqs); | 2610 | HEX_DISPLAY(dev->stats.irqs); |
2558 | LUB_DISC_BLNK_LED &= 0xff; | 2611 | LUB_DISC_BLNK_LED &= 0xff; |
2559 | #endif | 2612 | #endif |
2560 | } | 2613 | } else |
2561 | #endif | 2614 | #endif |
2615 | if (vbus_irq) { | ||
2616 | retval = request_irq(vbus_irq, udc_vbus_irq, | ||
2617 | SA_INTERRUPT | SA_SAMPLE_RANDOM, | ||
2618 | driver_name, dev); | ||
2619 | if (retval != 0) { | ||
2620 | printk(KERN_ERR "%s: can't get irq %i, err %d\n", | ||
2621 | driver_name, vbus_irq, retval); | ||
2622 | free_irq(IRQ_USB, dev); | ||
2623 | return -EBUSY; | ||
2624 | } | ||
2625 | } | ||
2562 | create_proc_files(); | 2626 | create_proc_files(); |
2563 | 2627 | ||
2564 | return 0; | 2628 | return 0; |
@@ -2587,6 +2651,8 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) | |||
2587 | free_irq(LUBBOCK_USB_IRQ, dev); | 2651 | free_irq(LUBBOCK_USB_IRQ, dev); |
2588 | } | 2652 | } |
2589 | #endif | 2653 | #endif |
2654 | if (dev->mach->gpio_vbus) | ||
2655 | free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev); | ||
2590 | platform_set_drvdata(pdev, NULL); | 2656 | platform_set_drvdata(pdev, NULL); |
2591 | the_controller = NULL; | 2657 | the_controller = NULL; |
2592 | return 0; | 2658 | return 0; |
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index 19a883f7d1b8..8e598c8bf4e3 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h | |||
@@ -177,27 +177,19 @@ struct pxa2xx_udc { | |||
177 | 177 | ||
178 | static struct pxa2xx_udc *the_controller; | 178 | static struct pxa2xx_udc *the_controller; |
179 | 179 | ||
180 | /* one GPIO should be used to detect VBUS from the host */ | 180 | static inline int pxa_gpio_get(unsigned gpio) |
181 | static inline int is_vbus_present(void) | ||
182 | { | 181 | { |
183 | if (!the_controller->mach->udc_is_connected) | 182 | return (GPLR(gpio) & GPIO_bit(gpio)) != 0; |
184 | return 1; | ||
185 | return the_controller->mach->udc_is_connected(); | ||
186 | } | 183 | } |
187 | 184 | ||
188 | /* one GPIO should control a D+ pullup, so host sees this device (or not) */ | 185 | static inline void pxa_gpio_set(unsigned gpio, int is_on) |
189 | static inline void pullup_off(void) | ||
190 | { | 186 | { |
191 | if (!the_controller->mach->udc_command) | 187 | int mask = GPIO_bit(gpio); |
192 | return; | ||
193 | the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); | ||
194 | } | ||
195 | 188 | ||
196 | static inline void pullup_on(void) | 189 | if (is_on) |
197 | { | 190 | GPSR(gpio) = mask; |
198 | if (!the_controller->mach->udc_command) | 191 | else |
199 | return; | 192 | GPCR(gpio) = mask; |
200 | the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); | ||
201 | } | 193 | } |
202 | 194 | ||
203 | /*-------------------------------------------------------------------------*/ | 195 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index e762aa19ab0a..b893e3118e1b 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -1120,12 +1120,15 @@ static int gs_send(struct gs_dev *dev) | |||
1120 | gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2)); | 1120 | gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2)); |
1121 | list_del(&req_entry->re_entry); | 1121 | list_del(&req_entry->re_entry); |
1122 | req->length = len; | 1122 | req->length = len; |
1123 | spin_unlock_irqrestore(&dev->dev_lock, flags); | ||
1123 | if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { | 1124 | if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { |
1124 | printk(KERN_ERR | 1125 | printk(KERN_ERR |
1125 | "gs_send: cannot queue read request, ret=%d\n", | 1126 | "gs_send: cannot queue read request, ret=%d\n", |
1126 | ret); | 1127 | ret); |
1128 | spin_lock_irqsave(&dev->dev_lock, flags); | ||
1127 | break; | 1129 | break; |
1128 | } | 1130 | } |
1131 | spin_lock_irqsave(&dev->dev_lock, flags); | ||
1129 | } else { | 1132 | } else { |
1130 | break; | 1133 | break; |
1131 | } | 1134 | } |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index b93d71d28db7..cf10cbc98f80 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -83,6 +83,7 @@ config USB_OHCI_HCD | |||
83 | tristate "OHCI HCD support" | 83 | tristate "OHCI HCD support" |
84 | depends on USB && USB_ARCH_HAS_OHCI | 84 | depends on USB && USB_ARCH_HAS_OHCI |
85 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 | 85 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 |
86 | select I2C if ARCH_PNX4008 | ||
86 | ---help--- | 87 | ---help--- |
87 | The Open Host Controller Interface (OHCI) is a standard for accessing | 88 | The Open Host Controller Interface (OHCI) is a standard for accessing |
88 | USB 1.1 host controller hardware. It does more in hardware than Intel's | 89 | USB 1.1 host controller hardware. It does more in hardware than Intel's |
@@ -141,6 +142,34 @@ config USB_UHCI_HCD | |||
141 | To compile this driver as a module, choose M here: the | 142 | To compile this driver as a module, choose M here: the |
142 | module will be called uhci-hcd. | 143 | module will be called uhci-hcd. |
143 | 144 | ||
145 | config USB_U132_HCD | ||
146 | tristate "Elan U132 Adapter Host Controller" | ||
147 | depends on USB && USB_FTDI_ELAN | ||
148 | default M | ||
149 | help | ||
150 | The U132 adapter is a USB to CardBus adapter specifically designed | ||
151 | for PC cards that contain an OHCI host controller. Typical PC cards | ||
152 | are the Orange Mobile 3G Option GlobeTrotter Fusion card. The U132 | ||
153 | adapter will *NOT* work with PC cards that do not contain an OHCI | ||
154 | controller. | ||
155 | |||
156 | For those PC cards that contain multiple OHCI controllers only ther | ||
157 | first one is used. | ||
158 | |||
159 | The driver consists of two modules, the "ftdi-elan" module is a | ||
160 | USB client driver that interfaces to the FTDI chip within ELAN's | ||
161 | USB-to-PCMCIA adapter, and this "u132-hcd" module is a USB host | ||
162 | controller driver that talks to the OHCI controller within the | ||
163 | CardBus cards that are inserted in the U132 adapter. | ||
164 | |||
165 | This driver has been tested with a CardBus OHCI USB adapter, and | ||
166 | worked with a USB PEN Drive inserted into the first USB port of | ||
167 | the PCCARD. A rather pointless thing to do, but useful for testing. | ||
168 | |||
169 | It is safe to say M here. | ||
170 | |||
171 | See also <http://www.elandigitalsystems.com/support/ufaq/u132linux.php> | ||
172 | |||
144 | config USB_SL811_HCD | 173 | config USB_SL811_HCD |
145 | tristate "SL811HS HCD support" | 174 | tristate "SL811HS HCD support" |
146 | depends on USB | 175 | depends on USB |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index e3020f4b17be..a2e58c86849f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -14,4 +14,5 @@ obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | |||
14 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | 14 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
15 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o | 15 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o |
16 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o | 16 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o |
17 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o | ||
17 | obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o | 18 | obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 26ed757d22a6..5d1b12aad776 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
@@ -200,6 +200,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { | |||
200 | .reset = ehci_init, | 200 | .reset = ehci_init, |
201 | .start = ehci_run, | 201 | .start = ehci_run, |
202 | .stop = ehci_stop, | 202 | .stop = ehci_stop, |
203 | .shutdown = ehci_shutdown, | ||
203 | 204 | ||
204 | /* | 205 | /* |
205 | * managing i/o requests and associated device resources | 206 | * managing i/o requests and associated device resources |
@@ -268,6 +269,7 @@ MODULE_ALIAS("au1xxx-ehci"); | |||
268 | static struct platform_driver ehci_hcd_au1xxx_driver = { | 269 | static struct platform_driver ehci_hcd_au1xxx_driver = { |
269 | .probe = ehci_hcd_au1xxx_drv_probe, | 270 | .probe = ehci_hcd_au1xxx_drv_probe, |
270 | .remove = ehci_hcd_au1xxx_drv_remove, | 271 | .remove = ehci_hcd_au1xxx_drv_remove, |
272 | .shutdown = usb_hcd_platform_shutdown, | ||
271 | /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ | 273 | /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ |
272 | /*.resume = ehci_hcd_au1xxx_drv_resume, */ | 274 | /*.resume = ehci_hcd_au1xxx_drv_resume, */ |
273 | .driver = { | 275 | .driver = { |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 65ac9fef3a7c..23b95b2bfe15 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (c) 2001-2002 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
6 | * Free Software Foundation; either version 2 of the License, or (at your | 6 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -65,7 +65,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) | |||
65 | for (i = 0; i < HCS_N_PORTS (params); i++) { | 65 | for (i = 0; i < HCS_N_PORTS (params); i++) { |
66 | // FIXME MIPS won't readb() ... | 66 | // FIXME MIPS won't readb() ... |
67 | byte = readb (&ehci->caps->portroute[(i>>1)]); | 67 | byte = readb (&ehci->caps->portroute[(i>>1)]); |
68 | sprintf(tmp, "%d ", | 68 | sprintf(tmp, "%d ", |
69 | ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); | 69 | ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); |
70 | strcat(buf, tmp); | 70 | strcat(buf, tmp); |
71 | } | 71 | } |
@@ -141,12 +141,12 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
141 | } | 141 | } |
142 | 142 | ||
143 | static void __attribute__((__unused__)) | 143 | static void __attribute__((__unused__)) |
144 | dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) | 144 | dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) |
145 | { | 145 | { |
146 | ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", | 146 | ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", |
147 | label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb); | 147 | label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb); |
148 | ehci_dbg (ehci, | 148 | ehci_dbg (ehci, |
149 | " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", | 149 | " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", |
150 | le32_to_cpu(itd->hw_transaction[0]), | 150 | le32_to_cpu(itd->hw_transaction[0]), |
151 | le32_to_cpu(itd->hw_transaction[1]), | 151 | le32_to_cpu(itd->hw_transaction[1]), |
152 | le32_to_cpu(itd->hw_transaction[2]), | 152 | le32_to_cpu(itd->hw_transaction[2]), |
@@ -156,7 +156,7 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) | |||
156 | le32_to_cpu(itd->hw_transaction[6]), | 156 | le32_to_cpu(itd->hw_transaction[6]), |
157 | le32_to_cpu(itd->hw_transaction[7])); | 157 | le32_to_cpu(itd->hw_transaction[7])); |
158 | ehci_dbg (ehci, | 158 | ehci_dbg (ehci, |
159 | " buf: %08x %08x %08x %08x %08x %08x %08x\n", | 159 | " buf: %08x %08x %08x %08x %08x %08x %08x\n", |
160 | le32_to_cpu(itd->hw_bufp[0]), | 160 | le32_to_cpu(itd->hw_bufp[0]), |
161 | le32_to_cpu(itd->hw_bufp[1]), | 161 | le32_to_cpu(itd->hw_bufp[1]), |
162 | le32_to_cpu(itd->hw_bufp[2]), | 162 | le32_to_cpu(itd->hw_bufp[2]), |
@@ -171,12 +171,12 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) | |||
171 | } | 171 | } |
172 | 172 | ||
173 | static void __attribute__((__unused__)) | 173 | static void __attribute__((__unused__)) |
174 | dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) | 174 | dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) |
175 | { | 175 | { |
176 | ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", | 176 | ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", |
177 | label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb); | 177 | label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb); |
178 | ehci_dbg (ehci, | 178 | ehci_dbg (ehci, |
179 | " addr %08x sched %04x result %08x buf %08x %08x\n", | 179 | " addr %08x sched %04x result %08x buf %08x %08x\n", |
180 | le32_to_cpu(sitd->hw_fullspeed_ep), | 180 | le32_to_cpu(sitd->hw_fullspeed_ep), |
181 | le32_to_cpu(sitd->hw_uframe), | 181 | le32_to_cpu(sitd->hw_uframe), |
182 | le32_to_cpu(sitd->hw_results), | 182 | le32_to_cpu(sitd->hw_results), |
@@ -451,7 +451,7 @@ show_async (struct class_device *class_dev, char *buf) | |||
451 | *buf = 0; | 451 | *buf = 0; |
452 | 452 | ||
453 | bus = class_get_devdata(class_dev); | 453 | bus = class_get_devdata(class_dev); |
454 | hcd = bus->hcpriv; | 454 | hcd = bus_to_hcd(bus); |
455 | ehci = hcd_to_ehci (hcd); | 455 | ehci = hcd_to_ehci (hcd); |
456 | next = buf; | 456 | next = buf; |
457 | size = PAGE_SIZE; | 457 | size = PAGE_SIZE; |
@@ -497,7 +497,7 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
497 | seen_count = 0; | 497 | seen_count = 0; |
498 | 498 | ||
499 | bus = class_get_devdata(class_dev); | 499 | bus = class_get_devdata(class_dev); |
500 | hcd = bus->hcpriv; | 500 | hcd = bus_to_hcd(bus); |
501 | ehci = hcd_to_ehci (hcd); | 501 | ehci = hcd_to_ehci (hcd); |
502 | next = buf; | 502 | next = buf; |
503 | size = PAGE_SIZE; | 503 | size = PAGE_SIZE; |
@@ -634,7 +634,7 @@ show_registers (struct class_device *class_dev, char *buf) | |||
634 | static char label [] = ""; | 634 | static char label [] = ""; |
635 | 635 | ||
636 | bus = class_get_devdata(class_dev); | 636 | bus = class_get_devdata(class_dev); |
637 | hcd = bus->hcpriv; | 637 | hcd = bus_to_hcd(bus); |
638 | ehci = hcd_to_ehci (hcd); | 638 | ehci = hcd_to_ehci (hcd); |
639 | next = buf; | 639 | next = buf; |
640 | size = PAGE_SIZE; | 640 | size = PAGE_SIZE; |
@@ -754,9 +754,7 @@ show_registers (struct class_device *class_dev, char *buf) | |||
754 | } | 754 | } |
755 | 755 | ||
756 | if (ehci->reclaim) { | 756 | if (ehci->reclaim) { |
757 | temp = scnprintf (next, size, "reclaim qh %p%s\n", | 757 | temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim); |
758 | ehci->reclaim, | ||
759 | ehci->reclaim_ready ? " ready" : ""); | ||
760 | size -= temp; | 758 | size -= temp; |
761 | next += temp; | 759 | next += temp; |
762 | } | 760 | } |
@@ -785,10 +783,11 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); | |||
785 | static inline void create_debug_files (struct ehci_hcd *ehci) | 783 | static inline void create_debug_files (struct ehci_hcd *ehci) |
786 | { | 784 | { |
787 | struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev; | 785 | struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev; |
786 | int retval; | ||
788 | 787 | ||
789 | class_device_create_file(cldev, &class_device_attr_async); | 788 | retval = class_device_create_file(cldev, &class_device_attr_async); |
790 | class_device_create_file(cldev, &class_device_attr_periodic); | 789 | retval = class_device_create_file(cldev, &class_device_attr_periodic); |
791 | class_device_create_file(cldev, &class_device_attr_registers); | 790 | retval = class_device_create_file(cldev, &class_device_attr_registers); |
792 | } | 791 | } |
793 | 792 | ||
794 | static inline void remove_debug_files (struct ehci_hcd *ehci) | 793 | static inline void remove_debug_files (struct ehci_hcd *ehci) |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index d030516edfb9..1a915e982c1c 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -285,6 +285,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { | |||
285 | .resume = ehci_bus_resume, | 285 | .resume = ehci_bus_resume, |
286 | #endif | 286 | #endif |
287 | .stop = ehci_stop, | 287 | .stop = ehci_stop, |
288 | .shutdown = ehci_shutdown, | ||
288 | 289 | ||
289 | /* | 290 | /* |
290 | * managing i/o requests and associated device resources | 291 | * managing i/o requests and associated device resources |
@@ -329,6 +330,7 @@ MODULE_ALIAS("fsl-ehci"); | |||
329 | static struct platform_driver ehci_fsl_driver = { | 330 | static struct platform_driver ehci_fsl_driver = { |
330 | .probe = ehci_fsl_drv_probe, | 331 | .probe = ehci_fsl_drv_probe, |
331 | .remove = ehci_fsl_drv_remove, | 332 | .remove = ehci_fsl_drv_remove, |
333 | .shutdown = usb_hcd_platform_shutdown, | ||
332 | .driver = { | 334 | .driver = { |
333 | .name = "fsl-ehci", | 335 | .name = "fsl-ehci", |
334 | }, | 336 | }, |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d63177a8eaea..5ac918591131 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2004 by David Brownell | 2 | * Copyright (c) 2000-2004 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
6 | * Free Software Foundation; either version 2 of the License, or (at your | 6 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -70,7 +70,7 @@ | |||
70 | * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared; | 70 | * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared; |
71 | * only scheduling is different, no arbitrary limitations. | 71 | * only scheduling is different, no arbitrary limitations. |
72 | * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support, | 72 | * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support, |
73 | * clean up HC run state handshaking. | 73 | * clean up HC run state handshaking. |
74 | * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts | 74 | * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts |
75 | * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other | 75 | * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other |
76 | * missing pieces: enabling 64bit dma, handoff from BIOS/SMM. | 76 | * missing pieces: enabling 64bit dma, handoff from BIOS/SMM. |
@@ -111,7 +111,7 @@ static const char hcd_name [] = "ehci_hcd"; | |||
111 | #define EHCI_TUNE_MULT_TT 1 | 111 | #define EHCI_TUNE_MULT_TT 1 |
112 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | 112 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ |
113 | 113 | ||
114 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ | 114 | #define EHCI_IAA_MSECS 10 /* arbitrary */ |
115 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | 115 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ |
116 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | 116 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ |
117 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ | 117 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ |
@@ -254,6 +254,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
254 | 254 | ||
255 | /*-------------------------------------------------------------------------*/ | 255 | /*-------------------------------------------------------------------------*/ |
256 | 256 | ||
257 | static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs); | ||
257 | static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs); | 258 | static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs); |
258 | 259 | ||
259 | #include "ehci-hub.c" | 260 | #include "ehci-hub.c" |
@@ -263,28 +264,39 @@ static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs); | |||
263 | 264 | ||
264 | /*-------------------------------------------------------------------------*/ | 265 | /*-------------------------------------------------------------------------*/ |
265 | 266 | ||
266 | static void ehci_watchdog (unsigned long param) | 267 | static void ehci_iaa_watchdog (unsigned long param) |
267 | { | 268 | { |
268 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | 269 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; |
269 | unsigned long flags; | 270 | unsigned long flags; |
271 | u32 status; | ||
270 | 272 | ||
271 | spin_lock_irqsave (&ehci->lock, flags); | 273 | spin_lock_irqsave (&ehci->lock, flags); |
274 | WARN_ON(!ehci->reclaim); | ||
272 | 275 | ||
273 | /* lost IAA irqs wedge things badly; seen with a vt8235 */ | 276 | /* lost IAA irqs wedge things badly; seen first with a vt8235 */ |
274 | if (ehci->reclaim) { | 277 | if (ehci->reclaim) { |
275 | u32 status = readl (&ehci->regs->status); | 278 | status = readl (&ehci->regs->status); |
276 | |||
277 | if (status & STS_IAA) { | 279 | if (status & STS_IAA) { |
278 | ehci_vdbg (ehci, "lost IAA\n"); | 280 | ehci_vdbg (ehci, "lost IAA\n"); |
279 | COUNT (ehci->stats.lost_iaa); | 281 | COUNT (ehci->stats.lost_iaa); |
280 | writel (STS_IAA, &ehci->regs->status); | 282 | writel (STS_IAA, &ehci->regs->status); |
281 | ehci->reclaim_ready = 1; | 283 | end_unlink_async (ehci, NULL); |
282 | } | 284 | } |
283 | } | 285 | } |
284 | 286 | ||
285 | /* stop async processing after it's idled a bit */ | 287 | spin_unlock_irqrestore (&ehci->lock, flags); |
288 | } | ||
289 | |||
290 | static void ehci_watchdog (unsigned long param) | ||
291 | { | ||
292 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | ||
293 | unsigned long flags; | ||
294 | |||
295 | spin_lock_irqsave (&ehci->lock, flags); | ||
296 | |||
297 | /* stop async processing after it's idled a bit */ | ||
286 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) | 298 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) |
287 | start_unlink_async (ehci, ehci->async); | 299 | start_unlink_async (ehci, ehci->async); |
288 | 300 | ||
289 | /* ehci could run by timer, without IRQs ... */ | 301 | /* ehci could run by timer, without IRQs ... */ |
290 | ehci_work (ehci, NULL); | 302 | ehci_work (ehci, NULL); |
@@ -292,21 +304,20 @@ static void ehci_watchdog (unsigned long param) | |||
292 | spin_unlock_irqrestore (&ehci->lock, flags); | 304 | spin_unlock_irqrestore (&ehci->lock, flags); |
293 | } | 305 | } |
294 | 306 | ||
295 | /* Reboot notifiers kick in for silicon on any bus (not just pci, etc). | 307 | /* ehci_shutdown kick in for silicon on any bus (not just pci, etc). |
296 | * This forcibly disables dma and IRQs, helping kexec and other cases | 308 | * This forcibly disables dma and IRQs, helping kexec and other cases |
297 | * where the next system software may expect clean state. | 309 | * where the next system software may expect clean state. |
298 | */ | 310 | */ |
299 | static int | 311 | static void |
300 | ehci_reboot (struct notifier_block *self, unsigned long code, void *null) | 312 | ehci_shutdown (struct usb_hcd *hcd) |
301 | { | 313 | { |
302 | struct ehci_hcd *ehci; | 314 | struct ehci_hcd *ehci; |
303 | 315 | ||
304 | ehci = container_of (self, struct ehci_hcd, reboot_notifier); | 316 | ehci = hcd_to_ehci (hcd); |
305 | (void) ehci_halt (ehci); | 317 | (void) ehci_halt (ehci); |
306 | 318 | ||
307 | /* make BIOS/etc use companion controller during reboot */ | 319 | /* make BIOS/etc use companion controller during reboot */ |
308 | writel (0, &ehci->regs->configured_flag); | 320 | writel (0, &ehci->regs->configured_flag); |
309 | return 0; | ||
310 | } | 321 | } |
311 | 322 | ||
312 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | 323 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) |
@@ -334,8 +345,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | |||
334 | static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) | 345 | static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) |
335 | { | 346 | { |
336 | timer_action_done (ehci, TIMER_IO_WATCHDOG); | 347 | timer_action_done (ehci, TIMER_IO_WATCHDOG); |
337 | if (ehci->reclaim_ready) | ||
338 | end_unlink_async (ehci, regs); | ||
339 | 348 | ||
340 | /* another CPU may drop ehci->lock during a schedule scan while | 349 | /* another CPU may drop ehci->lock during a schedule scan while |
341 | * it reports urb completions. this flag guards against bogus | 350 | * it reports urb completions. this flag guards against bogus |
@@ -370,6 +379,7 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
370 | 379 | ||
371 | /* no more interrupts ... */ | 380 | /* no more interrupts ... */ |
372 | del_timer_sync (&ehci->watchdog); | 381 | del_timer_sync (&ehci->watchdog); |
382 | del_timer_sync (&ehci->iaa_watchdog); | ||
373 | 383 | ||
374 | spin_lock_irq(&ehci->lock); | 384 | spin_lock_irq(&ehci->lock); |
375 | if (HC_IS_RUNNING (hcd->state)) | 385 | if (HC_IS_RUNNING (hcd->state)) |
@@ -381,7 +391,6 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
381 | 391 | ||
382 | /* let companion controllers work when we aren't */ | 392 | /* let companion controllers work when we aren't */ |
383 | writel (0, &ehci->regs->configured_flag); | 393 | writel (0, &ehci->regs->configured_flag); |
384 | unregister_reboot_notifier (&ehci->reboot_notifier); | ||
385 | 394 | ||
386 | remove_debug_files (ehci); | 395 | remove_debug_files (ehci); |
387 | 396 | ||
@@ -417,6 +426,10 @@ static int ehci_init(struct usb_hcd *hcd) | |||
417 | ehci->watchdog.function = ehci_watchdog; | 426 | ehci->watchdog.function = ehci_watchdog; |
418 | ehci->watchdog.data = (unsigned long) ehci; | 427 | ehci->watchdog.data = (unsigned long) ehci; |
419 | 428 | ||
429 | init_timer(&ehci->iaa_watchdog); | ||
430 | ehci->iaa_watchdog.function = ehci_iaa_watchdog; | ||
431 | ehci->iaa_watchdog.data = (unsigned long) ehci; | ||
432 | |||
420 | /* | 433 | /* |
421 | * hw default: 1K periodic list heads, one per frame. | 434 | * hw default: 1K periodic list heads, one per frame. |
422 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 435 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
@@ -427,13 +440,12 @@ static int ehci_init(struct usb_hcd *hcd) | |||
427 | 440 | ||
428 | /* controllers may cache some of the periodic schedule ... */ | 441 | /* controllers may cache some of the periodic schedule ... */ |
429 | hcc_params = readl(&ehci->caps->hcc_params); | 442 | hcc_params = readl(&ehci->caps->hcc_params); |
430 | if (HCC_ISOC_CACHE(hcc_params)) // full frame cache | 443 | if (HCC_ISOC_CACHE(hcc_params)) // full frame cache |
431 | ehci->i_thresh = 8; | 444 | ehci->i_thresh = 8; |
432 | else // N microframes cached | 445 | else // N microframes cached |
433 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); | 446 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); |
434 | 447 | ||
435 | ehci->reclaim = NULL; | 448 | ehci->reclaim = NULL; |
436 | ehci->reclaim_ready = 0; | ||
437 | ehci->next_uframe = -1; | 449 | ehci->next_uframe = -1; |
438 | 450 | ||
439 | /* | 451 | /* |
@@ -483,9 +495,6 @@ static int ehci_init(struct usb_hcd *hcd) | |||
483 | } | 495 | } |
484 | ehci->command = temp; | 496 | ehci->command = temp; |
485 | 497 | ||
486 | ehci->reboot_notifier.notifier_call = ehci_reboot; | ||
487 | register_reboot_notifier(&ehci->reboot_notifier); | ||
488 | |||
489 | return 0; | 498 | return 0; |
490 | } | 499 | } |
491 | 500 | ||
@@ -499,7 +508,6 @@ static int ehci_run (struct usb_hcd *hcd) | |||
499 | 508 | ||
500 | /* EHCI spec section 4.1 */ | 509 | /* EHCI spec section 4.1 */ |
501 | if ((retval = ehci_reset(ehci)) != 0) { | 510 | if ((retval = ehci_reset(ehci)) != 0) { |
502 | unregister_reboot_notifier(&ehci->reboot_notifier); | ||
503 | ehci_mem_cleanup(ehci); | 511 | ehci_mem_cleanup(ehci); |
504 | return retval; | 512 | return retval; |
505 | } | 513 | } |
@@ -611,7 +619,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) | |||
611 | /* complete the unlinking of some qh [4.15.2.3] */ | 619 | /* complete the unlinking of some qh [4.15.2.3] */ |
612 | if (status & STS_IAA) { | 620 | if (status & STS_IAA) { |
613 | COUNT (ehci->stats.reclaim); | 621 | COUNT (ehci->stats.reclaim); |
614 | ehci->reclaim_ready = 1; | 622 | end_unlink_async (ehci, regs); |
615 | bh = 1; | 623 | bh = 1; |
616 | } | 624 | } |
617 | 625 | ||
@@ -715,10 +723,14 @@ static int ehci_urb_enqueue ( | |||
715 | 723 | ||
716 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | 724 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
717 | { | 725 | { |
718 | /* if we need to use IAA and it's busy, defer */ | 726 | // BUG_ON(qh->qh_state != QH_STATE_LINKED); |
719 | if (qh->qh_state == QH_STATE_LINKED | 727 | |
720 | && ehci->reclaim | 728 | /* failfast */ |
721 | && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { | 729 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) |
730 | end_unlink_async (ehci, NULL); | ||
731 | |||
732 | /* defer till later if busy */ | ||
733 | else if (ehci->reclaim) { | ||
722 | struct ehci_qh *last; | 734 | struct ehci_qh *last; |
723 | 735 | ||
724 | for (last = ehci->reclaim; | 736 | for (last = ehci->reclaim; |
@@ -728,12 +740,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
728 | qh->qh_state = QH_STATE_UNLINK_WAIT; | 740 | qh->qh_state = QH_STATE_UNLINK_WAIT; |
729 | last->reclaim = qh; | 741 | last->reclaim = qh; |
730 | 742 | ||
731 | /* bypass IAA if the hc can't care */ | 743 | /* start IAA cycle */ |
732 | } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) | 744 | } else |
733 | end_unlink_async (ehci, NULL); | ||
734 | |||
735 | /* something else might have unlinked the qh by now */ | ||
736 | if (qh->qh_state == QH_STATE_LINKED) | ||
737 | start_unlink_async (ehci, qh); | 745 | start_unlink_async (ehci, qh); |
738 | } | 746 | } |
739 | 747 | ||
@@ -755,7 +763,19 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
755 | qh = (struct ehci_qh *) urb->hcpriv; | 763 | qh = (struct ehci_qh *) urb->hcpriv; |
756 | if (!qh) | 764 | if (!qh) |
757 | break; | 765 | break; |
758 | unlink_async (ehci, qh); | 766 | switch (qh->qh_state) { |
767 | case QH_STATE_LINKED: | ||
768 | case QH_STATE_COMPLETING: | ||
769 | unlink_async (ehci, qh); | ||
770 | break; | ||
771 | case QH_STATE_UNLINK: | ||
772 | case QH_STATE_UNLINK_WAIT: | ||
773 | /* already started */ | ||
774 | break; | ||
775 | case QH_STATE_IDLE: | ||
776 | WARN_ON(1); | ||
777 | break; | ||
778 | } | ||
759 | break; | 779 | break; |
760 | 780 | ||
761 | case PIPE_INTERRUPT: | 781 | case PIPE_INTERRUPT: |
@@ -847,6 +867,7 @@ rescan: | |||
847 | unlink_async (ehci, qh); | 867 | unlink_async (ehci, qh); |
848 | /* FALL THROUGH */ | 868 | /* FALL THROUGH */ |
849 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | 869 | case QH_STATE_UNLINK: /* wait for hw to finish? */ |
870 | case QH_STATE_UNLINK_WAIT: | ||
850 | idle_timeout: | 871 | idle_timeout: |
851 | spin_unlock_irqrestore (&ehci->lock, flags); | 872 | spin_unlock_irqrestore (&ehci->lock, flags); |
852 | schedule_timeout_uninterruptible(1); | 873 | schedule_timeout_uninterruptible(1); |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d03e3cad5ca8..b2ee13c58517 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001-2004 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
6 | * Free Software Foundation; either version 2 of the License, or (at your | 6 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
48 | } | 48 | } |
49 | ehci->command = readl (&ehci->regs->command); | 49 | ehci->command = readl (&ehci->regs->command); |
50 | if (ehci->reclaim) | 50 | if (ehci->reclaim) |
51 | ehci->reclaim_ready = 1; | 51 | end_unlink_async (ehci, NULL); |
52 | ehci_work(ehci, NULL); | 52 | ehci_work(ehci, NULL); |
53 | 53 | ||
54 | /* suspend any active/unsuspended ports, maybe allow wakeup */ | 54 | /* suspend any active/unsuspended ports, maybe allow wakeup */ |
@@ -103,10 +103,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
103 | 103 | ||
104 | /* re-init operational registers in case we lost power */ | 104 | /* re-init operational registers in case we lost power */ |
105 | if (readl (&ehci->regs->intr_enable) == 0) { | 105 | if (readl (&ehci->regs->intr_enable) == 0) { |
106 | /* at least some APM implementations will try to deliver | 106 | /* at least some APM implementations will try to deliver |
107 | * IRQs right away, so delay them until we're ready. | 107 | * IRQs right away, so delay them until we're ready. |
108 | */ | 108 | */ |
109 | intr_enable = 1; | 109 | intr_enable = 1; |
110 | writel (0, &ehci->regs->segment); | 110 | writel (0, &ehci->regs->segment); |
111 | writel (ehci->periodic_dma, &ehci->regs->frame_list); | 111 | writel (ehci->periodic_dma, &ehci->regs->frame_list); |
112 | writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); | 112 | writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); |
@@ -232,7 +232,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
232 | buf [1] = 0; | 232 | buf [1] = 0; |
233 | retval++; | 233 | retval++; |
234 | } | 234 | } |
235 | 235 | ||
236 | /* no hub change reports (bit 0) for now (power, ...) */ | 236 | /* no hub change reports (bit 0) for now (power, ...) */ |
237 | 237 | ||
238 | /* port N changes (bit N)? */ | 238 | /* port N changes (bit N)? */ |
@@ -304,7 +304,7 @@ ehci_hub_descriptor ( | |||
304 | 304 | ||
305 | /*-------------------------------------------------------------------------*/ | 305 | /*-------------------------------------------------------------------------*/ |
306 | 306 | ||
307 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) | 307 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) |
308 | 308 | ||
309 | static int ehci_hub_control ( | 309 | static int ehci_hub_control ( |
310 | struct usb_hcd *hcd, | 310 | struct usb_hcd *hcd, |
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 766061e0260a..a8ba2e1497a4 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001 by David Brownell | 2 | * Copyright (c) 2001 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
6 | * Free Software Foundation; either version 2 of the License, or (at your | 6 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -25,7 +25,7 @@ | |||
25 | * - data used only by the HCD ... kmalloc is fine | 25 | * - data used only by the HCD ... kmalloc is fine |
26 | * - async and periodic schedules, shared by HC and HCD ... these | 26 | * - async and periodic schedules, shared by HC and HCD ... these |
27 | * need to use dma_pool or dma_alloc_coherent | 27 | * need to use dma_pool or dma_alloc_coherent |
28 | * - driver buffers, read/written by HC ... single shot DMA mapped | 28 | * - driver buffers, read/written by HC ... single shot DMA mapped |
29 | * | 29 | * |
30 | * There's also PCI "register" data, which is memory mapped. | 30 | * There's also PCI "register" data, which is memory mapped. |
31 | * No memory seen by this driver is pageable. | 31 | * No memory seen by this driver is pageable. |
@@ -119,7 +119,7 @@ static inline void qh_put (struct ehci_qh *qh) | |||
119 | 119 | ||
120 | /*-------------------------------------------------------------------------*/ | 120 | /*-------------------------------------------------------------------------*/ |
121 | 121 | ||
122 | /* The queue heads and transfer descriptors are managed from pools tied | 122 | /* The queue heads and transfer descriptors are managed from pools tied |
123 | * to each of the "per device" structures. | 123 | * to each of the "per device" structures. |
124 | * This is the initialisation and cleanup code. | 124 | * This is the initialisation and cleanup code. |
125 | */ | 125 | */ |
@@ -165,7 +165,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
165 | int i; | 165 | int i; |
166 | 166 | ||
167 | /* QTDs for control/bulk/intr transfers */ | 167 | /* QTDs for control/bulk/intr transfers */ |
168 | ehci->qtd_pool = dma_pool_create ("ehci_qtd", | 168 | ehci->qtd_pool = dma_pool_create ("ehci_qtd", |
169 | ehci_to_hcd(ehci)->self.controller, | 169 | ehci_to_hcd(ehci)->self.controller, |
170 | sizeof (struct ehci_qtd), | 170 | sizeof (struct ehci_qtd), |
171 | 32 /* byte alignment (for hw parts) */, | 171 | 32 /* byte alignment (for hw parts) */, |
@@ -175,7 +175,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
175 | } | 175 | } |
176 | 176 | ||
177 | /* QHs for control/bulk/intr transfers */ | 177 | /* QHs for control/bulk/intr transfers */ |
178 | ehci->qh_pool = dma_pool_create ("ehci_qh", | 178 | ehci->qh_pool = dma_pool_create ("ehci_qh", |
179 | ehci_to_hcd(ehci)->self.controller, | 179 | ehci_to_hcd(ehci)->self.controller, |
180 | sizeof (struct ehci_qh), | 180 | sizeof (struct ehci_qh), |
181 | 32 /* byte alignment (for hw parts) */, | 181 | 32 /* byte alignment (for hw parts) */, |
@@ -189,7 +189,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
189 | } | 189 | } |
190 | 190 | ||
191 | /* ITD for high speed ISO transfers */ | 191 | /* ITD for high speed ISO transfers */ |
192 | ehci->itd_pool = dma_pool_create ("ehci_itd", | 192 | ehci->itd_pool = dma_pool_create ("ehci_itd", |
193 | ehci_to_hcd(ehci)->self.controller, | 193 | ehci_to_hcd(ehci)->self.controller, |
194 | sizeof (struct ehci_itd), | 194 | sizeof (struct ehci_itd), |
195 | 32 /* byte alignment (for hw parts) */, | 195 | 32 /* byte alignment (for hw parts) */, |
@@ -199,7 +199,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | /* SITD for full/low speed split ISO transfers */ | 201 | /* SITD for full/low speed split ISO transfers */ |
202 | ehci->sitd_pool = dma_pool_create ("ehci_sitd", | 202 | ehci->sitd_pool = dma_pool_create ("ehci_sitd", |
203 | ehci_to_hcd(ehci)->self.controller, | 203 | ehci_to_hcd(ehci)->self.controller, |
204 | sizeof (struct ehci_sitd), | 204 | sizeof (struct ehci_sitd), |
205 | 32 /* byte alignment (for hw parts) */, | 205 | 32 /* byte alignment (for hw parts) */, |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index cadffacd945b..08d0472d4f57 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -238,6 +238,12 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
238 | writel (0, &ehci->regs->intr_enable); | 238 | writel (0, &ehci->regs->intr_enable); |
239 | (void)readl(&ehci->regs->intr_enable); | 239 | (void)readl(&ehci->regs->intr_enable); |
240 | 240 | ||
241 | /* make sure snapshot being resumed re-enumerates everything */ | ||
242 | if (message.event == PM_EVENT_PRETHAW) { | ||
243 | ehci_halt(ehci); | ||
244 | ehci_reset(ehci); | ||
245 | } | ||
246 | |||
241 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 247 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
242 | bail: | 248 | bail: |
243 | spin_unlock_irqrestore (&ehci->lock, flags); | 249 | spin_unlock_irqrestore (&ehci->lock, flags); |
@@ -297,7 +303,7 @@ restart: | |||
297 | /* emptying the schedule aborts any urbs */ | 303 | /* emptying the schedule aborts any urbs */ |
298 | spin_lock_irq(&ehci->lock); | 304 | spin_lock_irq(&ehci->lock); |
299 | if (ehci->reclaim) | 305 | if (ehci->reclaim) |
300 | ehci->reclaim_ready = 1; | 306 | end_unlink_async (ehci, NULL); |
301 | ehci_work(ehci, NULL); | 307 | ehci_work(ehci, NULL); |
302 | spin_unlock_irq(&ehci->lock); | 308 | spin_unlock_irq(&ehci->lock); |
303 | 309 | ||
@@ -332,6 +338,7 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
332 | .resume = ehci_pci_resume, | 338 | .resume = ehci_pci_resume, |
333 | #endif | 339 | #endif |
334 | .stop = ehci_stop, | 340 | .stop = ehci_stop, |
341 | .shutdown = ehci_shutdown, | ||
335 | 342 | ||
336 | /* | 343 | /* |
337 | * managing i/o requests and associated device resources | 344 | * managing i/o requests and associated device resources |
@@ -378,4 +385,5 @@ static struct pci_driver ehci_pci_driver = { | |||
378 | .suspend = usb_hcd_pci_suspend, | 385 | .suspend = usb_hcd_pci_suspend, |
379 | .resume = usb_hcd_pci_resume, | 386 | .resume = usb_hcd_pci_resume, |
380 | #endif | 387 | #endif |
388 | .shutdown = usb_hcd_pci_shutdown, | ||
381 | }; | 389 | }; |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index e469221e7ec3..7fc25b6bd7d2 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001-2004 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
6 | * Free Software Foundation; either version 2 of the License, or (at your | 6 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -31,7 +31,7 @@ | |||
31 | * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with | 31 | * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with |
32 | * interrupts) needs careful scheduling. Performance improvements can be | 32 | * interrupts) needs careful scheduling. Performance improvements can be |
33 | * an ongoing challenge. That's in "ehci-sched.c". | 33 | * an ongoing challenge. That's in "ehci-sched.c". |
34 | * | 34 | * |
35 | * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, | 35 | * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, |
36 | * or otherwise through transaction translators (TTs) in USB 2.0 hubs using | 36 | * or otherwise through transaction translators (TTs) in USB 2.0 hubs using |
37 | * (b) special fields in qh entries or (c) split iso entries. TTs will | 37 | * (b) special fields in qh entries or (c) split iso entries. TTs will |
@@ -199,7 +199,7 @@ static void qtd_copy_status ( | |||
199 | && ((token & QTD_STS_MMF) != 0 | 199 | && ((token & QTD_STS_MMF) != 0 |
200 | || QTD_CERR(token) == 0) | 200 | || QTD_CERR(token) == 0) |
201 | && (!ehci_is_TDI(ehci) | 201 | && (!ehci_is_TDI(ehci) |
202 | || urb->dev->tt->hub != | 202 | || urb->dev->tt->hub != |
203 | ehci_to_hcd(ehci)->self.root_hub)) { | 203 | ehci_to_hcd(ehci)->self.root_hub)) { |
204 | #ifdef DEBUG | 204 | #ifdef DEBUG |
205 | struct usb_device *tt = urb->dev->tt->hub; | 205 | struct usb_device *tt = urb->dev->tt->hub; |
@@ -364,7 +364,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs) | |||
364 | */ | 364 | */ |
365 | if (likely (urb->status == -EINPROGRESS)) | 365 | if (likely (urb->status == -EINPROGRESS)) |
366 | continue; | 366 | continue; |
367 | 367 | ||
368 | /* issue status after short control reads */ | 368 | /* issue status after short control reads */ |
369 | if (unlikely (do_status != 0) | 369 | if (unlikely (do_status != 0) |
370 | && QTD_PID (token) == 0 /* OUT */) { | 370 | && QTD_PID (token) == 0 /* OUT */) { |
@@ -388,7 +388,7 @@ halt: | |||
388 | wmb (); | 388 | wmb (); |
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | /* remove it from the queue */ | 392 | /* remove it from the queue */ |
393 | spin_lock (&urb->lock); | 393 | spin_lock (&urb->lock); |
394 | qtd_copy_status (ehci, urb, qtd->length, token); | 394 | qtd_copy_status (ehci, urb, qtd->length, token); |
@@ -518,7 +518,7 @@ qh_urb_transaction ( | |||
518 | /* for zero length DATA stages, STATUS is always IN */ | 518 | /* for zero length DATA stages, STATUS is always IN */ |
519 | if (len == 0) | 519 | if (len == 0) |
520 | token |= (1 /* "in" */ << 8); | 520 | token |= (1 /* "in" */ << 8); |
521 | } | 521 | } |
522 | 522 | ||
523 | /* | 523 | /* |
524 | * data transfer stage: buffer setup | 524 | * data transfer stage: buffer setup |
@@ -759,7 +759,7 @@ qh_make ( | |||
759 | } | 759 | } |
760 | break; | 760 | break; |
761 | default: | 761 | default: |
762 | dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed); | 762 | dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed); |
763 | done: | 763 | done: |
764 | qh_put (qh); | 764 | qh_put (qh); |
765 | return NULL; | 765 | return NULL; |
@@ -967,17 +967,16 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) | |||
967 | struct ehci_qh *qh = ehci->reclaim; | 967 | struct ehci_qh *qh = ehci->reclaim; |
968 | struct ehci_qh *next; | 968 | struct ehci_qh *next; |
969 | 969 | ||
970 | timer_action_done (ehci, TIMER_IAA_WATCHDOG); | 970 | iaa_watchdog_done (ehci); |
971 | 971 | ||
972 | // qh->hw_next = cpu_to_le32 (qh->qh_dma); | 972 | // qh->hw_next = cpu_to_le32 (qh->qh_dma); |
973 | qh->qh_state = QH_STATE_IDLE; | 973 | qh->qh_state = QH_STATE_IDLE; |
974 | qh->qh_next.qh = NULL; | 974 | qh->qh_next.qh = NULL; |
975 | qh_put (qh); // refcount from reclaim | 975 | qh_put (qh); // refcount from reclaim |
976 | 976 | ||
977 | /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ | 977 | /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ |
978 | next = qh->reclaim; | 978 | next = qh->reclaim; |
979 | ehci->reclaim = next; | 979 | ehci->reclaim = next; |
980 | ehci->reclaim_ready = 0; | ||
981 | qh->reclaim = NULL; | 980 | qh->reclaim = NULL; |
982 | 981 | ||
983 | qh_completions (ehci, qh, regs); | 982 | qh_completions (ehci, qh, regs); |
@@ -1031,7 +1030,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1031 | timer_action_done (ehci, TIMER_ASYNC_OFF); | 1030 | timer_action_done (ehci, TIMER_ASYNC_OFF); |
1032 | } | 1031 | } |
1033 | return; | 1032 | return; |
1034 | } | 1033 | } |
1035 | 1034 | ||
1036 | qh->qh_state = QH_STATE_UNLINK; | 1035 | qh->qh_state = QH_STATE_UNLINK; |
1037 | ehci->reclaim = qh = qh_get (qh); | 1036 | ehci->reclaim = qh = qh_get (qh); |
@@ -1046,17 +1045,16 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1046 | 1045 | ||
1047 | if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { | 1046 | if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { |
1048 | /* if (unlikely (qh->reclaim != 0)) | 1047 | /* if (unlikely (qh->reclaim != 0)) |
1049 | * this will recurse, probably not much | 1048 | * this will recurse, probably not much |
1050 | */ | 1049 | */ |
1051 | end_unlink_async (ehci, NULL); | 1050 | end_unlink_async (ehci, NULL); |
1052 | return; | 1051 | return; |
1053 | } | 1052 | } |
1054 | 1053 | ||
1055 | ehci->reclaim_ready = 0; | ||
1056 | cmd |= CMD_IAAD; | 1054 | cmd |= CMD_IAAD; |
1057 | writel (cmd, &ehci->regs->command); | 1055 | writel (cmd, &ehci->regs->command); |
1058 | (void) readl (&ehci->regs->command); | 1056 | (void) readl (&ehci->regs->command); |
1059 | timer_action (ehci, TIMER_IAA_WATCHDOG); | 1057 | iaa_watchdog_start (ehci); |
1060 | } | 1058 | } |
1061 | 1059 | ||
1062 | /*-------------------------------------------------------------------------*/ | 1060 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 4859900bd135..e5e9c653c907 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2004 by David Brownell | 2 | * Copyright (c) 2001-2004 by David Brownell |
3 | * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers | 3 | * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License as published by the | 6 | * under the terms of the GNU General Public License as published by the |
7 | * Free Software Foundation; either version 2 of the License, or (at your | 7 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -613,7 +613,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
613 | /*-------------------------------------------------------------------------*/ | 613 | /*-------------------------------------------------------------------------*/ |
614 | 614 | ||
615 | static int check_period ( | 615 | static int check_period ( |
616 | struct ehci_hcd *ehci, | 616 | struct ehci_hcd *ehci, |
617 | unsigned frame, | 617 | unsigned frame, |
618 | unsigned uframe, | 618 | unsigned uframe, |
619 | unsigned period, | 619 | unsigned period, |
@@ -629,7 +629,7 @@ static int check_period ( | |||
629 | 629 | ||
630 | /* | 630 | /* |
631 | * 80% periodic == 100 usec/uframe available | 631 | * 80% periodic == 100 usec/uframe available |
632 | * convert "usecs we need" to "max already claimed" | 632 | * convert "usecs we need" to "max already claimed" |
633 | */ | 633 | */ |
634 | usecs = 100 - usecs; | 634 | usecs = 100 - usecs; |
635 | 635 | ||
@@ -659,14 +659,14 @@ static int check_period ( | |||
659 | } | 659 | } |
660 | 660 | ||
661 | static int check_intr_schedule ( | 661 | static int check_intr_schedule ( |
662 | struct ehci_hcd *ehci, | 662 | struct ehci_hcd *ehci, |
663 | unsigned frame, | 663 | unsigned frame, |
664 | unsigned uframe, | 664 | unsigned uframe, |
665 | const struct ehci_qh *qh, | 665 | const struct ehci_qh *qh, |
666 | __le32 *c_maskp | 666 | __le32 *c_maskp |
667 | ) | 667 | ) |
668 | { | 668 | { |
669 | int retval = -ENOSPC; | 669 | int retval = -ENOSPC; |
670 | u8 mask = 0; | 670 | u8 mask = 0; |
671 | 671 | ||
672 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ | 672 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ |
@@ -701,7 +701,7 @@ static int check_intr_schedule ( | |||
701 | /* Make sure this tt's buffer is also available for CSPLITs. | 701 | /* Make sure this tt's buffer is also available for CSPLITs. |
702 | * We pessimize a bit; probably the typical full speed case | 702 | * We pessimize a bit; probably the typical full speed case |
703 | * doesn't need the second CSPLIT. | 703 | * doesn't need the second CSPLIT. |
704 | * | 704 | * |
705 | * NOTE: both SPLIT and CSPLIT could be checked in just | 705 | * NOTE: both SPLIT and CSPLIT could be checked in just |
706 | * one smart pass... | 706 | * one smart pass... |
707 | */ | 707 | */ |
@@ -728,7 +728,7 @@ done: | |||
728 | */ | 728 | */ |
729 | static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | 729 | static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) |
730 | { | 730 | { |
731 | int status; | 731 | int status; |
732 | unsigned uframe; | 732 | unsigned uframe; |
733 | __le32 c_mask; | 733 | __le32 c_mask; |
734 | unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ | 734 | unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ |
@@ -784,7 +784,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
784 | ehci_dbg (ehci, "reused qh %p schedule\n", qh); | 784 | ehci_dbg (ehci, "reused qh %p schedule\n", qh); |
785 | 785 | ||
786 | /* stuff into the periodic schedule */ | 786 | /* stuff into the periodic schedule */ |
787 | status = qh_link_periodic (ehci, qh); | 787 | status = qh_link_periodic (ehci, qh); |
788 | done: | 788 | done: |
789 | return status; | 789 | return status; |
790 | } | 790 | } |
@@ -1681,7 +1681,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
1681 | status = -ESHUTDOWN; | 1681 | status = -ESHUTDOWN; |
1682 | else | 1682 | else |
1683 | status = iso_stream_schedule (ehci, urb, stream); | 1683 | status = iso_stream_schedule (ehci, urb, stream); |
1684 | if (likely (status == 0)) | 1684 | if (likely (status == 0)) |
1685 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 1685 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
1686 | spin_unlock_irqrestore (&ehci->lock, flags); | 1686 | spin_unlock_irqrestore (&ehci->lock, flags); |
1687 | 1687 | ||
@@ -1738,7 +1738,7 @@ sitd_sched_init ( | |||
1738 | if (packet->buf1 != (buf & ~(u64)0x0fff)) | 1738 | if (packet->buf1 != (buf & ~(u64)0x0fff)) |
1739 | packet->cross = 1; | 1739 | packet->cross = 1; |
1740 | 1740 | ||
1741 | /* OUT uses multiple start-splits */ | 1741 | /* OUT uses multiple start-splits */ |
1742 | if (stream->bEndpointAddress & USB_DIR_IN) | 1742 | if (stream->bEndpointAddress & USB_DIR_IN) |
1743 | continue; | 1743 | continue; |
1744 | length = (length + 187) / 188; | 1744 | length = (length + 187) / 188; |
@@ -1925,7 +1925,7 @@ sitd_link_urb ( | |||
1925 | /*-------------------------------------------------------------------------*/ | 1925 | /*-------------------------------------------------------------------------*/ |
1926 | 1926 | ||
1927 | #define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ | 1927 | #define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ |
1928 | | SITD_STS_XACT | SITD_STS_MMF) | 1928 | | SITD_STS_XACT | SITD_STS_MMF) |
1929 | 1929 | ||
1930 | static unsigned | 1930 | static unsigned |
1931 | sitd_complete ( | 1931 | sitd_complete ( |
@@ -2043,7 +2043,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
2043 | status = -ESHUTDOWN; | 2043 | status = -ESHUTDOWN; |
2044 | else | 2044 | else |
2045 | status = iso_stream_schedule (ehci, urb, stream); | 2045 | status = iso_stream_schedule (ehci, urb, stream); |
2046 | if (status == 0) | 2046 | if (status == 0) |
2047 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 2047 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
2048 | spin_unlock_irqrestore (&ehci->lock, flags); | 2048 | spin_unlock_irqrestore (&ehci->lock, flags); |
2049 | 2049 | ||
@@ -2226,5 +2226,5 @@ restart: | |||
2226 | now_uframe++; | 2226 | now_uframe++; |
2227 | now_uframe %= mod; | 2227 | now_uframe %= mod; |
2228 | } | 2228 | } |
2229 | } | 2229 | } |
2230 | } | 2230 | } |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 679c1cdcc915..6aac39f50e07 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (c) 2001-2002 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
6 | * Free Software Foundation; either version 2 of the License, or (at your | 6 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -58,7 +58,6 @@ struct ehci_hcd { /* one per controller */ | |||
58 | /* async schedule support */ | 58 | /* async schedule support */ |
59 | struct ehci_qh *async; | 59 | struct ehci_qh *async; |
60 | struct ehci_qh *reclaim; | 60 | struct ehci_qh *reclaim; |
61 | unsigned reclaim_ready : 1; | ||
62 | unsigned scanning : 1; | 61 | unsigned scanning : 1; |
63 | 62 | ||
64 | /* periodic schedule support */ | 63 | /* periodic schedule support */ |
@@ -81,8 +80,8 @@ struct ehci_hcd { /* one per controller */ | |||
81 | struct dma_pool *itd_pool; /* itd per iso urb */ | 80 | struct dma_pool *itd_pool; /* itd per iso urb */ |
82 | struct dma_pool *sitd_pool; /* sitd per split iso urb */ | 81 | struct dma_pool *sitd_pool; /* sitd per split iso urb */ |
83 | 82 | ||
83 | struct timer_list iaa_watchdog; | ||
84 | struct timer_list watchdog; | 84 | struct timer_list watchdog; |
85 | struct notifier_block reboot_notifier; | ||
86 | unsigned long actions; | 85 | unsigned long actions; |
87 | unsigned stamp; | 86 | unsigned stamp; |
88 | unsigned long next_statechange; | 87 | unsigned long next_statechange; |
@@ -104,7 +103,7 @@ struct ehci_hcd { /* one per controller */ | |||
104 | #endif | 103 | #endif |
105 | }; | 104 | }; |
106 | 105 | ||
107 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ | 106 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ |
108 | static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd) | 107 | static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd) |
109 | { | 108 | { |
110 | return (struct ehci_hcd *) (hcd->hcd_priv); | 109 | return (struct ehci_hcd *) (hcd->hcd_priv); |
@@ -115,9 +114,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) | |||
115 | } | 114 | } |
116 | 115 | ||
117 | 116 | ||
117 | static inline void | ||
118 | iaa_watchdog_start (struct ehci_hcd *ehci) | ||
119 | { | ||
120 | WARN_ON(timer_pending(&ehci->iaa_watchdog)); | ||
121 | mod_timer (&ehci->iaa_watchdog, | ||
122 | jiffies + msecs_to_jiffies(EHCI_IAA_MSECS)); | ||
123 | } | ||
124 | |||
125 | static inline void iaa_watchdog_done (struct ehci_hcd *ehci) | ||
126 | { | ||
127 | del_timer (&ehci->iaa_watchdog); | ||
128 | } | ||
129 | |||
118 | enum ehci_timer_action { | 130 | enum ehci_timer_action { |
119 | TIMER_IO_WATCHDOG, | 131 | TIMER_IO_WATCHDOG, |
120 | TIMER_IAA_WATCHDOG, | ||
121 | TIMER_ASYNC_SHRINK, | 132 | TIMER_ASYNC_SHRINK, |
122 | TIMER_ASYNC_OFF, | 133 | TIMER_ASYNC_OFF, |
123 | }; | 134 | }; |
@@ -135,9 +146,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
135 | unsigned long t; | 146 | unsigned long t; |
136 | 147 | ||
137 | switch (action) { | 148 | switch (action) { |
138 | case TIMER_IAA_WATCHDOG: | ||
139 | t = EHCI_IAA_JIFFIES; | ||
140 | break; | ||
141 | case TIMER_IO_WATCHDOG: | 149 | case TIMER_IO_WATCHDOG: |
142 | t = EHCI_IO_JIFFIES; | 150 | t = EHCI_IO_JIFFIES; |
143 | break; | 151 | break; |
@@ -154,8 +162,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
154 | // async queue SHRINK often precedes IAA. while it's ready | 162 | // async queue SHRINK often precedes IAA. while it's ready |
155 | // to go OFF neither can matter, and afterwards the IO | 163 | // to go OFF neither can matter, and afterwards the IO |
156 | // watchdog stops unless there's still periodic traffic. | 164 | // watchdog stops unless there's still periodic traffic. |
157 | if (action != TIMER_IAA_WATCHDOG | 165 | if (time_before_eq(t, ehci->watchdog.expires) |
158 | && t > ehci->watchdog.expires | ||
159 | && timer_pending (&ehci->watchdog)) | 166 | && timer_pending (&ehci->watchdog)) |
160 | return; | 167 | return; |
161 | mod_timer (&ehci->watchdog, t); | 168 | mod_timer (&ehci->watchdog, t); |
@@ -179,8 +186,8 @@ struct ehci_caps { | |||
179 | #define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ | 186 | #define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ |
180 | #define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ | 187 | #define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ |
181 | #define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ | 188 | #define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ |
182 | #define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ | 189 | #define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ |
183 | #define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ | 190 | #define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ |
184 | #define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ | 191 | #define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ |
185 | 192 | ||
186 | u32 hcc_params; /* HCCPARAMS - offset 0x8 */ | 193 | u32 hcc_params; /* HCCPARAMS - offset 0x8 */ |
@@ -205,7 +212,7 @@ struct ehci_regs { | |||
205 | #define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ | 212 | #define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ |
206 | #define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ | 213 | #define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ |
207 | #define CMD_ASE (1<<5) /* async schedule enable */ | 214 | #define CMD_ASE (1<<5) /* async schedule enable */ |
208 | #define CMD_PSE (1<<4) /* periodic schedule enable */ | 215 | #define CMD_PSE (1<<4) /* periodic schedule enable */ |
209 | /* 3:2 is periodic frame list size */ | 216 | /* 3:2 is periodic frame list size */ |
210 | #define CMD_RESET (1<<1) /* reset HC not bus */ | 217 | #define CMD_RESET (1<<1) /* reset HC not bus */ |
211 | #define CMD_RUN (1<<0) /* start/stop HC */ | 218 | #define CMD_RUN (1<<0) /* start/stop HC */ |
@@ -231,9 +238,9 @@ struct ehci_regs { | |||
231 | /* FRINDEX: offset 0x0C */ | 238 | /* FRINDEX: offset 0x0C */ |
232 | u32 frame_index; /* current microframe number */ | 239 | u32 frame_index; /* current microframe number */ |
233 | /* CTRLDSSEGMENT: offset 0x10 */ | 240 | /* CTRLDSSEGMENT: offset 0x10 */ |
234 | u32 segment; /* address bits 63:32 if needed */ | 241 | u32 segment; /* address bits 63:32 if needed */ |
235 | /* PERIODICLISTBASE: offset 0x14 */ | 242 | /* PERIODICLISTBASE: offset 0x14 */ |
236 | u32 frame_list; /* points to periodic list */ | 243 | u32 frame_list; /* points to periodic list */ |
237 | /* ASYNCLISTADDR: offset 0x18 */ | 244 | /* ASYNCLISTADDR: offset 0x18 */ |
238 | u32 async_next; /* address of next async queue head */ | 245 | u32 async_next; /* address of next async queue head */ |
239 | 246 | ||
@@ -302,7 +309,7 @@ struct ehci_dbg_port { | |||
302 | 309 | ||
303 | /* | 310 | /* |
304 | * EHCI Specification 0.95 Section 3.5 | 311 | * EHCI Specification 0.95 Section 3.5 |
305 | * QTD: describe data transfer components (buffer, direction, ...) | 312 | * QTD: describe data transfer components (buffer, direction, ...) |
306 | * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". | 313 | * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". |
307 | * | 314 | * |
308 | * These are associated only with "QH" (Queue Head) structures, | 315 | * These are associated only with "QH" (Queue Head) structures, |
@@ -312,7 +319,7 @@ struct ehci_qtd { | |||
312 | /* first part defined by EHCI spec */ | 319 | /* first part defined by EHCI spec */ |
313 | __le32 hw_next; /* see EHCI 3.5.1 */ | 320 | __le32 hw_next; /* see EHCI 3.5.1 */ |
314 | __le32 hw_alt_next; /* see EHCI 3.5.2 */ | 321 | __le32 hw_alt_next; /* see EHCI 3.5.2 */ |
315 | __le32 hw_token; /* see EHCI 3.5.3 */ | 322 | __le32 hw_token; /* see EHCI 3.5.3 */ |
316 | #define QTD_TOGGLE (1 << 31) /* data toggle */ | 323 | #define QTD_TOGGLE (1 << 31) /* data toggle */ |
317 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) | 324 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) |
318 | #define QTD_IOC (1 << 15) /* interrupt on complete */ | 325 | #define QTD_IOC (1 << 15) /* interrupt on complete */ |
@@ -349,8 +356,8 @@ struct ehci_qtd { | |||
349 | /* values for that type tag */ | 356 | /* values for that type tag */ |
350 | #define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1) | 357 | #define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1) |
351 | #define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) | 358 | #define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) |
352 | #define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1) | 359 | #define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1) |
353 | #define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1) | 360 | #define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1) |
354 | 361 | ||
355 | /* next async queue entry, or pointer to interrupt/periodic QH */ | 362 | /* next async queue entry, or pointer to interrupt/periodic QH */ |
356 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) | 363 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) |
@@ -367,7 +374,7 @@ struct ehci_qtd { | |||
367 | * For entries in the async schedule, the type tag always says "qh". | 374 | * For entries in the async schedule, the type tag always says "qh". |
368 | */ | 375 | */ |
369 | union ehci_shadow { | 376 | union ehci_shadow { |
370 | struct ehci_qh *qh; /* Q_TYPE_QH */ | 377 | struct ehci_qh *qh; /* Q_TYPE_QH */ |
371 | struct ehci_itd *itd; /* Q_TYPE_ITD */ | 378 | struct ehci_itd *itd; /* Q_TYPE_ITD */ |
372 | struct ehci_sitd *sitd; /* Q_TYPE_SITD */ | 379 | struct ehci_sitd *sitd; /* Q_TYPE_SITD */ |
373 | struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ | 380 | struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ |
@@ -397,7 +404,7 @@ struct ehci_qh { | |||
397 | #define QH_HUBPORT 0x3f800000 | 404 | #define QH_HUBPORT 0x3f800000 |
398 | #define QH_MULT 0xc0000000 | 405 | #define QH_MULT 0xc0000000 |
399 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ | 406 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ |
400 | 407 | ||
401 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ | 408 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ |
402 | __le32 hw_qtd_next; | 409 | __le32 hw_qtd_next; |
403 | __le32 hw_alt_next; | 410 | __le32 hw_alt_next; |
@@ -472,7 +479,7 @@ struct ehci_iso_stream { | |||
472 | struct list_head td_list; /* queued itds/sitds */ | 479 | struct list_head td_list; /* queued itds/sitds */ |
473 | struct list_head free_list; /* list of unused itds/sitds */ | 480 | struct list_head free_list; /* list of unused itds/sitds */ |
474 | struct usb_device *udev; | 481 | struct usb_device *udev; |
475 | struct usb_host_endpoint *ep; | 482 | struct usb_host_endpoint *ep; |
476 | 483 | ||
477 | /* output of (re)scheduling */ | 484 | /* output of (re)scheduling */ |
478 | unsigned long start; /* jiffies */ | 485 | unsigned long start; /* jiffies */ |
@@ -492,8 +499,8 @@ struct ehci_iso_stream { | |||
492 | unsigned bandwidth; | 499 | unsigned bandwidth; |
493 | 500 | ||
494 | /* This is used to initialize iTD's hw_bufp fields */ | 501 | /* This is used to initialize iTD's hw_bufp fields */ |
495 | __le32 buf0; | 502 | __le32 buf0; |
496 | __le32 buf1; | 503 | __le32 buf1; |
497 | __le32 buf2; | 504 | __le32 buf2; |
498 | 505 | ||
499 | /* this is used to initialize sITD's tt info */ | 506 | /* this is used to initialize sITD's tt info */ |
@@ -521,7 +528,7 @@ struct ehci_itd { | |||
521 | 528 | ||
522 | #define ITD_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE) | 529 | #define ITD_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE) |
523 | 530 | ||
524 | __le32 hw_bufp [7]; /* see EHCI 3.3.3 */ | 531 | __le32 hw_bufp [7]; /* see EHCI 3.3.3 */ |
525 | __le32 hw_bufp_hi [7]; /* Appendix B */ | 532 | __le32 hw_bufp_hi [7]; /* Appendix B */ |
526 | 533 | ||
527 | /* the rest is HCD-private */ | 534 | /* the rest is HCD-private */ |
@@ -542,7 +549,7 @@ struct ehci_itd { | |||
542 | /*-------------------------------------------------------------------------*/ | 549 | /*-------------------------------------------------------------------------*/ |
543 | 550 | ||
544 | /* | 551 | /* |
545 | * EHCI Specification 0.95 Section 3.4 | 552 | * EHCI Specification 0.95 Section 3.4 |
546 | * siTD, aka split-transaction isochronous Transfer Descriptor | 553 | * siTD, aka split-transaction isochronous Transfer Descriptor |
547 | * ... describe full speed iso xfers through TT in hubs | 554 | * ... describe full speed iso xfers through TT in hubs |
548 | * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) | 555 | * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 5147ed4a6662..a72e041df8e7 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -1204,10 +1204,10 @@ static int isp116x_show_dbg(struct seq_file *s, void *unused) | |||
1204 | 1204 | ||
1205 | static int isp116x_open_seq(struct inode *inode, struct file *file) | 1205 | static int isp116x_open_seq(struct inode *inode, struct file *file) |
1206 | { | 1206 | { |
1207 | return single_open(file, isp116x_show_dbg, inode->u.generic_ip); | 1207 | return single_open(file, isp116x_show_dbg, inode->i_private); |
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | static struct file_operations isp116x_debug_fops = { | 1210 | static const struct file_operations isp116x_debug_fops = { |
1211 | .open = isp116x_open_seq, | 1211 | .open = isp116x_open_seq, |
1212 | .read = seq_read, | 1212 | .read = seq_read, |
1213 | .llseek = seq_lseek, | 1213 | .llseek = seq_lseek, |
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index a1b7c3813d3a..b91e2edd9c5c 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h | |||
@@ -233,7 +233,7 @@ static const int cc_to_error[16] = { | |||
233 | /* Bit Stuff */ -EPROTO, | 233 | /* Bit Stuff */ -EPROTO, |
234 | /* Data Togg */ -EILSEQ, | 234 | /* Data Togg */ -EILSEQ, |
235 | /* Stall */ -EPIPE, | 235 | /* Stall */ -EPIPE, |
236 | /* DevNotResp */ -ETIMEDOUT, | 236 | /* DevNotResp */ -ETIME, |
237 | /* PIDCheck */ -EPROTO, | 237 | /* PIDCheck */ -EPROTO, |
238 | /* UnExpPID */ -EPROTO, | 238 | /* UnExpPID */ -EPROTO, |
239 | /* DataOver */ -EOVERFLOW, | 239 | /* DataOver */ -EOVERFLOW, |
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 85cc059705a6..b466581beb4a 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -193,7 +193,7 @@ ohci_at91_start (struct usb_hcd *hcd) | |||
193 | if ((ret = ohci_init(ohci)) < 0) | 193 | if ((ret = ohci_init(ohci)) < 0) |
194 | return ret; | 194 | return ret; |
195 | 195 | ||
196 | root->maxchild = board->ports; | 196 | ohci->num_ports = board->ports; |
197 | 197 | ||
198 | if ((ret = ohci_run(ohci)) < 0) { | 198 | if ((ret = ohci_run(ohci)) < 0) { |
199 | err("can't start %s", hcd->self.bus_name); | 199 | err("can't start %s", hcd->self.bus_name); |
@@ -221,6 +221,7 @@ static const struct hc_driver ohci_at91_hc_driver = { | |||
221 | */ | 221 | */ |
222 | .start = ohci_at91_start, | 222 | .start = ohci_at91_start, |
223 | .stop = ohci_stop, | 223 | .stop = ohci_stop, |
224 | .shutdown = ohci_shutdown, | ||
224 | 225 | ||
225 | /* | 226 | /* |
226 | * managing i/o requests and associated device resources | 227 | * managing i/o requests and associated device resources |
@@ -239,7 +240,7 @@ static const struct hc_driver ohci_at91_hc_driver = { | |||
239 | */ | 240 | */ |
240 | .hub_status_data = ohci_hub_status_data, | 241 | .hub_status_data = ohci_hub_status_data, |
241 | .hub_control = ohci_hub_control, | 242 | .hub_control = ohci_hub_control, |
242 | 243 | .hub_irq_enable = ohci_rhsc_enable, | |
243 | #ifdef CONFIG_PM | 244 | #ifdef CONFIG_PM |
244 | .bus_suspend = ohci_bus_suspend, | 245 | .bus_suspend = ohci_bus_suspend, |
245 | .bus_resume = ohci_bus_resume, | 246 | .bus_resume = ohci_bus_resume, |
@@ -296,6 +297,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) | |||
296 | if (!clocked) { | 297 | if (!clocked) { |
297 | clk_enable(iclk); | 298 | clk_enable(iclk); |
298 | clk_enable(fclk); | 299 | clk_enable(fclk); |
300 | clocked = 1; | ||
299 | } | 301 | } |
300 | 302 | ||
301 | return 0; | 303 | return 0; |
@@ -310,6 +312,7 @@ MODULE_ALIAS("at91_ohci"); | |||
310 | static struct platform_driver ohci_hcd_at91_driver = { | 312 | static struct platform_driver ohci_hcd_at91_driver = { |
311 | .probe = ohci_hcd_at91_drv_probe, | 313 | .probe = ohci_hcd_at91_drv_probe, |
312 | .remove = ohci_hcd_at91_drv_remove, | 314 | .remove = ohci_hcd_at91_drv_remove, |
315 | .shutdown = usb_hcd_platform_shutdown, | ||
313 | .suspend = ohci_hcd_at91_drv_suspend, | 316 | .suspend = ohci_hcd_at91_drv_suspend, |
314 | .resume = ohci_hcd_at91_drv_resume, | 317 | .resume = ohci_hcd_at91_drv_resume, |
315 | .driver = { | 318 | .driver = { |
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index f7a975d5db09..24e23c5783d8 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
@@ -268,11 +268,8 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { | |||
268 | * basic lifecycle operations | 268 | * basic lifecycle operations |
269 | */ | 269 | */ |
270 | .start = ohci_au1xxx_start, | 270 | .start = ohci_au1xxx_start, |
271 | #ifdef CONFIG_PM | ||
272 | /* suspend: ohci_au1xxx_suspend, -- tbd */ | ||
273 | /* resume: ohci_au1xxx_resume, -- tbd */ | ||
274 | #endif /*CONFIG_PM*/ | ||
275 | .stop = ohci_stop, | 271 | .stop = ohci_stop, |
272 | .shutdown = ohci_shutdown, | ||
276 | 273 | ||
277 | /* | 274 | /* |
278 | * managing i/o requests and associated device resources | 275 | * managing i/o requests and associated device resources |
@@ -291,6 +288,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { | |||
291 | */ | 288 | */ |
292 | .hub_status_data = ohci_hub_status_data, | 289 | .hub_status_data = ohci_hub_status_data, |
293 | .hub_control = ohci_hub_control, | 290 | .hub_control = ohci_hub_control, |
291 | .hub_irq_enable = ohci_rhsc_enable, | ||
294 | #ifdef CONFIG_PM | 292 | #ifdef CONFIG_PM |
295 | .bus_suspend = ohci_bus_suspend, | 293 | .bus_suspend = ohci_bus_suspend, |
296 | .bus_resume = ohci_bus_resume, | 294 | .bus_resume = ohci_bus_resume, |
@@ -338,6 +336,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev) | |||
338 | static struct platform_driver ohci_hcd_au1xxx_driver = { | 336 | static struct platform_driver ohci_hcd_au1xxx_driver = { |
339 | .probe = ohci_hcd_au1xxx_drv_probe, | 337 | .probe = ohci_hcd_au1xxx_drv_probe, |
340 | .remove = ohci_hcd_au1xxx_drv_remove, | 338 | .remove = ohci_hcd_au1xxx_drv_remove, |
339 | .shutdown = usb_hcd_platform_shutdown, | ||
341 | /*.suspend = ohci_hcd_au1xxx_drv_suspend, */ | 340 | /*.suspend = ohci_hcd_au1xxx_drv_suspend, */ |
342 | /*.resume = ohci_hcd_au1xxx_drv_resume, */ | 341 | /*.resume = ohci_hcd_au1xxx_drv_resume, */ |
343 | .driver = { | 342 | .driver = { |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 7bfffcbbd226..8293c1d4be3f 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -477,7 +477,7 @@ show_async (struct class_device *class_dev, char *buf) | |||
477 | unsigned long flags; | 477 | unsigned long flags; |
478 | 478 | ||
479 | bus = class_get_devdata(class_dev); | 479 | bus = class_get_devdata(class_dev); |
480 | hcd = bus->hcpriv; | 480 | hcd = bus_to_hcd(bus); |
481 | ohci = hcd_to_ohci(hcd); | 481 | ohci = hcd_to_ohci(hcd); |
482 | 482 | ||
483 | /* display control and bulk lists together, for simplicity */ | 483 | /* display control and bulk lists together, for simplicity */ |
@@ -510,7 +510,7 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
510 | seen_count = 0; | 510 | seen_count = 0; |
511 | 511 | ||
512 | bus = class_get_devdata(class_dev); | 512 | bus = class_get_devdata(class_dev); |
513 | hcd = bus->hcpriv; | 513 | hcd = bus_to_hcd(bus); |
514 | ohci = hcd_to_ohci(hcd); | 514 | ohci = hcd_to_ohci(hcd); |
515 | next = buf; | 515 | next = buf; |
516 | size = PAGE_SIZE; | 516 | size = PAGE_SIZE; |
@@ -607,7 +607,7 @@ show_registers (struct class_device *class_dev, char *buf) | |||
607 | u32 rdata; | 607 | u32 rdata; |
608 | 608 | ||
609 | bus = class_get_devdata(class_dev); | 609 | bus = class_get_devdata(class_dev); |
610 | hcd = bus->hcpriv; | 610 | hcd = bus_to_hcd(bus); |
611 | ohci = hcd_to_ohci(hcd); | 611 | ohci = hcd_to_ohci(hcd); |
612 | regs = ohci->regs; | 612 | regs = ohci->regs; |
613 | next = buf; | 613 | next = buf; |
@@ -667,6 +667,11 @@ show_registers (struct class_device *class_dev, char *buf) | |||
667 | size -= temp; | 667 | size -= temp; |
668 | next += temp; | 668 | next += temp; |
669 | 669 | ||
670 | temp = scnprintf (next, size, "hub poll timer %s\n", | ||
671 | ohci_to_hcd(ohci)->poll_rh ? "ON" : "off"); | ||
672 | size -= temp; | ||
673 | next += temp; | ||
674 | |||
670 | /* roothub */ | 675 | /* roothub */ |
671 | ohci_dump_roothub (ohci, 1, &next, &size); | 676 | ohci_dump_roothub (ohci, 1, &next, &size); |
672 | 677 | ||
@@ -680,10 +685,11 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); | |||
680 | static inline void create_debug_files (struct ohci_hcd *ohci) | 685 | static inline void create_debug_files (struct ohci_hcd *ohci) |
681 | { | 686 | { |
682 | struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev; | 687 | struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev; |
688 | int retval; | ||
683 | 689 | ||
684 | class_device_create_file(cldev, &class_device_attr_async); | 690 | retval = class_device_create_file(cldev, &class_device_attr_async); |
685 | class_device_create_file(cldev, &class_device_attr_periodic); | 691 | retval = class_device_create_file(cldev, &class_device_attr_periodic); |
686 | class_device_create_file(cldev, &class_device_attr_registers); | 692 | retval = class_device_create_file(cldev, &class_device_attr_registers); |
687 | ohci_dbg (ohci, "created debug files\n"); | 693 | ohci_dbg (ohci, "created debug files\n"); |
688 | } | 694 | } |
689 | 695 | ||
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 6531c4d26527..1bf5e7a4e735 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c | |||
@@ -128,12 +128,14 @@ static struct hc_driver ohci_ep93xx_hc_driver = { | |||
128 | .flags = HCD_USB11 | HCD_MEMORY, | 128 | .flags = HCD_USB11 | HCD_MEMORY, |
129 | .start = ohci_ep93xx_start, | 129 | .start = ohci_ep93xx_start, |
130 | .stop = ohci_stop, | 130 | .stop = ohci_stop, |
131 | .shutdown = ohci_shutdown, | ||
131 | .urb_enqueue = ohci_urb_enqueue, | 132 | .urb_enqueue = ohci_urb_enqueue, |
132 | .urb_dequeue = ohci_urb_dequeue, | 133 | .urb_dequeue = ohci_urb_dequeue, |
133 | .endpoint_disable = ohci_endpoint_disable, | 134 | .endpoint_disable = ohci_endpoint_disable, |
134 | .get_frame_number = ohci_get_frame, | 135 | .get_frame_number = ohci_get_frame, |
135 | .hub_status_data = ohci_hub_status_data, | 136 | .hub_status_data = ohci_hub_status_data, |
136 | .hub_control = ohci_hub_control, | 137 | .hub_control = ohci_hub_control, |
138 | .hub_irq_enable = ohci_rhsc_enable, | ||
137 | #ifdef CONFIG_PM | 139 | #ifdef CONFIG_PM |
138 | .bus_suspend = ohci_bus_suspend, | 140 | .bus_suspend = ohci_bus_suspend, |
139 | .bus_resume = ohci_bus_resume, | 141 | .bus_resume = ohci_bus_resume, |
@@ -202,6 +204,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) | |||
202 | static struct platform_driver ohci_hcd_ep93xx_driver = { | 204 | static struct platform_driver ohci_hcd_ep93xx_driver = { |
203 | .probe = ohci_hcd_ep93xx_drv_probe, | 205 | .probe = ohci_hcd_ep93xx_drv_probe, |
204 | .remove = ohci_hcd_ep93xx_drv_remove, | 206 | .remove = ohci_hcd_ep93xx_drv_remove, |
207 | .shutdown = usb_hcd_platform_shutdown, | ||
205 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM |
206 | .suspend = ohci_hcd_ep93xx_drv_suspend, | 209 | .suspend = ohci_hcd_ep93xx_drv_suspend, |
207 | .resume = ohci_hcd_ep93xx_drv_resume, | 210 | .resume = ohci_hcd_ep93xx_drv_resume, |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 94d8cf4b36c1..1027aa04583d 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -88,7 +88,7 @@ | |||
88 | #include <linux/timer.h> | 88 | #include <linux/timer.h> |
89 | #include <linux/list.h> | 89 | #include <linux/list.h> |
90 | #include <linux/usb.h> | 90 | #include <linux/usb.h> |
91 | #include <linux/usb_otg.h> | 91 | #include <linux/usb/otg.h> |
92 | #include <linux/dma-mapping.h> | 92 | #include <linux/dma-mapping.h> |
93 | #include <linux/dmapool.h> | 93 | #include <linux/dmapool.h> |
94 | #include <linux/reboot.h> | 94 | #include <linux/reboot.h> |
@@ -101,7 +101,7 @@ | |||
101 | 101 | ||
102 | #include "../core/hcd.h" | 102 | #include "../core/hcd.h" |
103 | 103 | ||
104 | #define DRIVER_VERSION "2005 April 22" | 104 | #define DRIVER_VERSION "2006 August 04" |
105 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" | 105 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" |
106 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" | 106 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" |
107 | 107 | ||
@@ -110,9 +110,10 @@ | |||
110 | #undef OHCI_VERBOSE_DEBUG /* not always helpful */ | 110 | #undef OHCI_VERBOSE_DEBUG /* not always helpful */ |
111 | 111 | ||
112 | /* For initializing controller (mask in an HCFS mode too) */ | 112 | /* For initializing controller (mask in an HCFS mode too) */ |
113 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR | 113 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR |
114 | #define OHCI_INTR_INIT \ | 114 | #define OHCI_INTR_INIT \ |
115 | (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH) | 115 | (OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE \ |
116 | | OHCI_INTR_RD | OHCI_INTR_WDH) | ||
116 | 117 | ||
117 | #ifdef __hppa__ | 118 | #ifdef __hppa__ |
118 | /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ | 119 | /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ |
@@ -128,12 +129,13 @@ | |||
128 | 129 | ||
129 | static const char hcd_name [] = "ohci_hcd"; | 130 | static const char hcd_name [] = "ohci_hcd"; |
130 | 131 | ||
132 | #define STATECHANGE_DELAY msecs_to_jiffies(300) | ||
133 | |||
131 | #include "ohci.h" | 134 | #include "ohci.h" |
132 | 135 | ||
133 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); | 136 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); |
134 | static int ohci_init (struct ohci_hcd *ohci); | 137 | static int ohci_init (struct ohci_hcd *ohci); |
135 | static void ohci_stop (struct usb_hcd *hcd); | 138 | static void ohci_stop (struct usb_hcd *hcd); |
136 | static int ohci_reboot (struct notifier_block *, unsigned long , void *); | ||
137 | 139 | ||
138 | #include "ohci-hub.c" | 140 | #include "ohci-hub.c" |
139 | #include "ohci-dbg.c" | 141 | #include "ohci-dbg.c" |
@@ -416,21 +418,20 @@ static void ohci_usb_reset (struct ohci_hcd *ohci) | |||
416 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 418 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
417 | } | 419 | } |
418 | 420 | ||
419 | /* reboot notifier forcibly disables IRQs and DMA, helping kexec and | 421 | /* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and |
420 | * other cases where the next software may expect clean state from the | 422 | * other cases where the next software may expect clean state from the |
421 | * "firmware". this is bus-neutral, unlike shutdown() methods. | 423 | * "firmware". this is bus-neutral, unlike shutdown() methods. |
422 | */ | 424 | */ |
423 | static int | 425 | static void |
424 | ohci_reboot (struct notifier_block *block, unsigned long code, void *null) | 426 | ohci_shutdown (struct usb_hcd *hcd) |
425 | { | 427 | { |
426 | struct ohci_hcd *ohci; | 428 | struct ohci_hcd *ohci; |
427 | 429 | ||
428 | ohci = container_of (block, struct ohci_hcd, reboot_notifier); | 430 | ohci = hcd_to_ohci (hcd); |
429 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 431 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
430 | ohci_usb_reset (ohci); | 432 | ohci_usb_reset (ohci); |
431 | /* flush the writes */ | 433 | /* flush the writes */ |
432 | (void) ohci_readl (ohci, &ohci->regs->control); | 434 | (void) ohci_readl (ohci, &ohci->regs->control); |
433 | return 0; | ||
434 | } | 435 | } |
435 | 436 | ||
436 | /*-------------------------------------------------------------------------* | 437 | /*-------------------------------------------------------------------------* |
@@ -446,7 +447,6 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
446 | 447 | ||
447 | disable (ohci); | 448 | disable (ohci); |
448 | ohci->regs = hcd->regs; | 449 | ohci->regs = hcd->regs; |
449 | ohci->next_statechange = jiffies; | ||
450 | 450 | ||
451 | /* REVISIT this BIOS handshake is now moved into PCI "quirks", and | 451 | /* REVISIT this BIOS handshake is now moved into PCI "quirks", and |
452 | * was never needed for most non-PCI systems ... remove the code? | 452 | * was never needed for most non-PCI systems ... remove the code? |
@@ -502,7 +502,6 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
502 | if ((ret = ohci_mem_init (ohci)) < 0) | 502 | if ((ret = ohci_mem_init (ohci)) < 0) |
503 | ohci_stop (hcd); | 503 | ohci_stop (hcd); |
504 | else { | 504 | else { |
505 | register_reboot_notifier (&ohci->reboot_notifier); | ||
506 | create_debug_files (ohci); | 505 | create_debug_files (ohci); |
507 | } | 506 | } |
508 | 507 | ||
@@ -637,10 +636,14 @@ retry: | |||
637 | return -EOVERFLOW; | 636 | return -EOVERFLOW; |
638 | } | 637 | } |
639 | 638 | ||
640 | /* start controller operations */ | 639 | /* use rhsc irqs after khubd is fully initialized */ |
640 | hcd->poll_rh = 1; | ||
641 | hcd->uses_new_polling = 1; | ||
642 | |||
643 | /* start controller operations */ | ||
641 | ohci->hc_control &= OHCI_CTRL_RWC; | 644 | ohci->hc_control &= OHCI_CTRL_RWC; |
642 | ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; | 645 | ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; |
643 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 646 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
644 | hcd->state = HC_STATE_RUNNING; | 647 | hcd->state = HC_STATE_RUNNING; |
645 | 648 | ||
646 | /* wake on ConnectStatusChange, matching external hubs */ | 649 | /* wake on ConnectStatusChange, matching external hubs */ |
@@ -648,7 +651,7 @@ retry: | |||
648 | 651 | ||
649 | /* Choose the interrupts we care about now, others later on demand */ | 652 | /* Choose the interrupts we care about now, others later on demand */ |
650 | mask = OHCI_INTR_INIT; | 653 | mask = OHCI_INTR_INIT; |
651 | ohci_writel (ohci, mask, &ohci->regs->intrstatus); | 654 | ohci_writel (ohci, ~0, &ohci->regs->intrstatus); |
652 | ohci_writel (ohci, mask, &ohci->regs->intrenable); | 655 | ohci_writel (ohci, mask, &ohci->regs->intrenable); |
653 | 656 | ||
654 | /* handle root hub init quirks ... */ | 657 | /* handle root hub init quirks ... */ |
@@ -672,6 +675,7 @@ retry: | |||
672 | // flush those writes | 675 | // flush those writes |
673 | (void) ohci_readl (ohci, &ohci->regs->control); | 676 | (void) ohci_readl (ohci, &ohci->regs->control); |
674 | 677 | ||
678 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | ||
675 | spin_unlock_irq (&ohci->lock); | 679 | spin_unlock_irq (&ohci->lock); |
676 | 680 | ||
677 | // POTPGT delay is bits 24-31, in 2 ms units. | 681 | // POTPGT delay is bits 24-31, in 2 ms units. |
@@ -709,7 +713,23 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) | |||
709 | /* interrupt for some other device? */ | 713 | /* interrupt for some other device? */ |
710 | } else if ((ints &= ohci_readl (ohci, ®s->intrenable)) == 0) { | 714 | } else if ((ints &= ohci_readl (ohci, ®s->intrenable)) == 0) { |
711 | return IRQ_NOTMINE; | 715 | return IRQ_NOTMINE; |
712 | } | 716 | } |
717 | |||
718 | /* NOTE: vendors didn't always make the same implementation | ||
719 | * choices for RHSC. Sometimes it triggers on an edge (like | ||
720 | * setting and maybe clearing a port status change bit); and | ||
721 | * it's level-triggered on other silicon, active until khubd | ||
722 | * clears all active port status change bits. Poll by timer | ||
723 | * til it's fully debounced and the difference won't matter. | ||
724 | */ | ||
725 | if (ints & OHCI_INTR_RHSC) { | ||
726 | ohci_vdbg (ohci, "rhsc\n"); | ||
727 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrdisable); | ||
728 | hcd->poll_rh = 1; | ||
729 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | ||
730 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus); | ||
731 | usb_hcd_poll_rh_status(hcd); | ||
732 | } | ||
713 | 733 | ||
714 | if (ints & OHCI_INTR_UE) { | 734 | if (ints & OHCI_INTR_UE) { |
715 | disable (ohci); | 735 | disable (ohci); |
@@ -775,9 +795,10 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
775 | 795 | ||
776 | ohci_usb_reset (ohci); | 796 | ohci_usb_reset (ohci); |
777 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 797 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
778 | 798 | free_irq(hcd->irq, hcd); | |
799 | hcd->irq = -1; | ||
800 | |||
779 | remove_debug_files (ohci); | 801 | remove_debug_files (ohci); |
780 | unregister_reboot_notifier (&ohci->reboot_notifier); | ||
781 | ohci_mem_cleanup (ohci); | 802 | ohci_mem_cleanup (ohci); |
782 | if (ohci->hcca) { | 803 | if (ohci->hcca) { |
783 | dma_free_coherent (hcd->self.controller, | 804 | dma_free_coherent (hcd->self.controller, |
@@ -917,6 +938,10 @@ MODULE_LICENSE ("GPL"); | |||
917 | #include "ohci-at91.c" | 938 | #include "ohci-at91.c" |
918 | #endif | 939 | #endif |
919 | 940 | ||
941 | #ifdef CONFIG_ARCH_PNX4008 | ||
942 | #include "ohci-pnx4008.c" | ||
943 | #endif | ||
944 | |||
920 | #if !(defined(CONFIG_PCI) \ | 945 | #if !(defined(CONFIG_PCI) \ |
921 | || defined(CONFIG_SA1111) \ | 946 | || defined(CONFIG_SA1111) \ |
922 | || defined(CONFIG_ARCH_S3C2410) \ | 947 | || defined(CONFIG_ARCH_S3C2410) \ |
@@ -928,6 +953,7 @@ MODULE_LICENSE ("GPL"); | |||
928 | || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ | 953 | || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ |
929 | || defined (CONFIG_ARCH_AT91RM9200) \ | 954 | || defined (CONFIG_ARCH_AT91RM9200) \ |
930 | || defined (CONFIG_ARCH_AT91SAM9261) \ | 955 | || defined (CONFIG_ARCH_AT91SAM9261) \ |
956 | || defined (CONFIG_ARCH_PNX4008) \ | ||
931 | ) | 957 | ) |
932 | #error "missing bus glue for ohci-hcd" | 958 | #error "missing bus glue for ohci-hcd" |
933 | #endif | 959 | #endif |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 5b0a23fd798b..0b899339cac8 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -36,6 +36,14 @@ | |||
36 | 36 | ||
37 | /*-------------------------------------------------------------------------*/ | 37 | /*-------------------------------------------------------------------------*/ |
38 | 38 | ||
39 | /* hcd->hub_irq_enable() */ | ||
40 | static void ohci_rhsc_enable (struct usb_hcd *hcd) | ||
41 | { | ||
42 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
43 | |||
44 | ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); | ||
45 | } | ||
46 | |||
39 | #ifdef CONFIG_PM | 47 | #ifdef CONFIG_PM |
40 | 48 | ||
41 | #define OHCI_SCHED_ENABLES \ | 49 | #define OHCI_SCHED_ENABLES \ |
@@ -123,10 +131,10 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) | |||
123 | /* no resumes until devices finish suspending */ | 131 | /* no resumes until devices finish suspending */ |
124 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); | 132 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); |
125 | 133 | ||
134 | /* no timer polling */ | ||
135 | hcd->poll_rh = 0; | ||
136 | |||
126 | done: | 137 | done: |
127 | /* external suspend vs self autosuspend ... same effect */ | ||
128 | if (status == 0) | ||
129 | usb_hcd_suspend_root_hub(hcd); | ||
130 | spin_unlock_irqrestore (&ohci->lock, flags); | 138 | spin_unlock_irqrestore (&ohci->lock, flags); |
131 | return status; | 139 | return status; |
132 | } | 140 | } |
@@ -256,8 +264,8 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
256 | /* TRSMRCY */ | 264 | /* TRSMRCY */ |
257 | msleep (10); | 265 | msleep (10); |
258 | 266 | ||
259 | /* keep it alive for ~5x suspend + resume costs */ | 267 | /* keep it alive for more than ~5x suspend + resume costs */ |
260 | ohci->next_statechange = jiffies + msecs_to_jiffies (250); | 268 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; |
261 | 269 | ||
262 | /* maybe turn schedules back on */ | 270 | /* maybe turn schedules back on */ |
263 | enables = 0; | 271 | enables = 0; |
@@ -302,9 +310,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
302 | { | 310 | { |
303 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 311 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
304 | int i, changed = 0, length = 1; | 312 | int i, changed = 0, length = 1; |
305 | int can_suspend = device_may_wakeup(&hcd->self.root_hub->dev); | 313 | int can_suspend; |
306 | unsigned long flags; | 314 | unsigned long flags; |
307 | 315 | ||
316 | can_suspend = device_may_wakeup(&hcd->self.root_hub->dev); | ||
308 | spin_lock_irqsave (&ohci->lock, flags); | 317 | spin_lock_irqsave (&ohci->lock, flags); |
309 | 318 | ||
310 | /* handle autosuspended root: finish resuming before | 319 | /* handle autosuspended root: finish resuming before |
@@ -339,6 +348,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
339 | for (i = 0; i < ohci->num_ports; i++) { | 348 | for (i = 0; i < ohci->num_ports; i++) { |
340 | u32 status = roothub_portstatus (ohci, i); | 349 | u32 status = roothub_portstatus (ohci, i); |
341 | 350 | ||
351 | /* can't autosuspend with active ports */ | ||
352 | if ((status & RH_PS_PES) && !(status & RH_PS_PSS)) | ||
353 | can_suspend = 0; | ||
354 | |||
342 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | 355 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC |
343 | | RH_PS_OCIC | RH_PS_PRSC)) { | 356 | | RH_PS_OCIC | RH_PS_PRSC)) { |
344 | changed = 1; | 357 | changed = 1; |
@@ -348,32 +361,41 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
348 | buf [1] |= 1 << (i - 7); | 361 | buf [1] |= 1 << (i - 7); |
349 | continue; | 362 | continue; |
350 | } | 363 | } |
364 | } | ||
351 | 365 | ||
352 | /* can suspend if no ports are enabled; or if all all | 366 | /* after root hub changes, stop polling after debouncing |
353 | * enabled ports are suspended AND remote wakeup is on. | 367 | * for a while and maybe kicking in autosuspend |
354 | */ | 368 | */ |
355 | if (!(status & RH_PS_CCS)) | 369 | if (changed) { |
356 | continue; | 370 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; |
357 | if ((status & RH_PS_PSS) && can_suspend) | ||
358 | continue; | ||
359 | can_suspend = 0; | 371 | can_suspend = 0; |
372 | } else if (time_before (jiffies, ohci->next_statechange)) { | ||
373 | can_suspend = 0; | ||
374 | } else { | ||
375 | #ifdef CONFIG_PM | ||
376 | can_suspend = can_suspend | ||
377 | && !ohci->ed_rm_list | ||
378 | && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) | ||
379 | & ohci->hc_control) | ||
380 | == OHCI_USB_OPER; | ||
381 | #endif | ||
382 | if (hcd->uses_new_polling) { | ||
383 | hcd->poll_rh = 0; | ||
384 | /* use INTR_RHSC iff INTR_RD won't apply */ | ||
385 | if (!can_suspend) | ||
386 | ohci_writel (ohci, OHCI_INTR_RHSC, | ||
387 | &ohci->regs->intrenable); | ||
388 | } | ||
360 | } | 389 | } |
390 | |||
361 | done: | 391 | done: |
362 | spin_unlock_irqrestore (&ohci->lock, flags); | 392 | spin_unlock_irqrestore (&ohci->lock, flags); |
363 | 393 | ||
364 | #ifdef CONFIG_PM | 394 | #ifdef CONFIG_PM |
365 | /* save power by suspending idle root hubs; | 395 | /* save power by autosuspending idle root hubs; |
366 | * INTR_RD wakes us when there's work | 396 | * INTR_RD wakes us when there's work |
367 | */ | 397 | */ |
368 | if (can_suspend | 398 | if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) { |
369 | && !changed | ||
370 | && !ohci->ed_rm_list | ||
371 | && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) | ||
372 | & ohci->hc_control) | ||
373 | == OHCI_USB_OPER | ||
374 | && time_after (jiffies, ohci->next_statechange) | ||
375 | && usb_trylock_device (hcd->self.root_hub) == 0 | ||
376 | ) { | ||
377 | ohci_vdbg (ohci, "autosuspend\n"); | 399 | ohci_vdbg (ohci, "autosuspend\n"); |
378 | (void) ohci_bus_suspend (hcd); | 400 | (void) ohci_bus_suspend (hcd); |
379 | usb_unlock_device (hcd->self.root_hub); | 401 | usb_unlock_device (hcd->self.root_hub); |
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 5602da9bd52c..e121d97ed91c 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c | |||
@@ -173,11 +173,8 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { | |||
173 | * basic lifecycle operations | 173 | * basic lifecycle operations |
174 | */ | 174 | */ |
175 | .start = ohci_lh7a404_start, | 175 | .start = ohci_lh7a404_start, |
176 | #ifdef CONFIG_PM | ||
177 | /* suspend: ohci_lh7a404_suspend, -- tbd */ | ||
178 | /* resume: ohci_lh7a404_resume, -- tbd */ | ||
179 | #endif /*CONFIG_PM*/ | ||
180 | .stop = ohci_stop, | 176 | .stop = ohci_stop, |
177 | .shutdown = ohci_shutdown, | ||
181 | 178 | ||
182 | /* | 179 | /* |
183 | * managing i/o requests and associated device resources | 180 | * managing i/o requests and associated device resources |
@@ -196,6 +193,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { | |||
196 | */ | 193 | */ |
197 | .hub_status_data = ohci_hub_status_data, | 194 | .hub_status_data = ohci_hub_status_data, |
198 | .hub_control = ohci_hub_control, | 195 | .hub_control = ohci_hub_control, |
196 | .hub_irq_enable = ohci_rhsc_enable, | ||
199 | #ifdef CONFIG_PM | 197 | #ifdef CONFIG_PM |
200 | .bus_suspend = ohci_bus_suspend, | 198 | .bus_suspend = ohci_bus_suspend, |
201 | .bus_resume = ohci_bus_resume, | 199 | .bus_resume = ohci_bus_resume, |
@@ -244,6 +242,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev) | |||
244 | static struct platform_driver ohci_hcd_lh7a404_driver = { | 242 | static struct platform_driver ohci_hcd_lh7a404_driver = { |
245 | .probe = ohci_hcd_lh7a404_drv_probe, | 243 | .probe = ohci_hcd_lh7a404_drv_probe, |
246 | .remove = ohci_hcd_lh7a404_drv_remove, | 244 | .remove = ohci_hcd_lh7a404_drv_remove, |
245 | .shutdown = usb_hcd_platform_shutdown, | ||
247 | /*.suspend = ohci_hcd_lh7a404_drv_suspend, */ | 246 | /*.suspend = ohci_hcd_lh7a404_drv_suspend, */ |
248 | /*.resume = ohci_hcd_lh7a404_drv_resume, */ | 247 | /*.resume = ohci_hcd_lh7a404_drv_resume, */ |
249 | .driver = { | 248 | .driver = { |
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index bfbe328a4788..d976614eebd3 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
@@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) | |||
28 | ohci->next_statechange = jiffies; | 28 | ohci->next_statechange = jiffies; |
29 | spin_lock_init (&ohci->lock); | 29 | spin_lock_init (&ohci->lock); |
30 | INIT_LIST_HEAD (&ohci->pending); | 30 | INIT_LIST_HEAD (&ohci->pending); |
31 | ohci->reboot_notifier.notifier_call = ohci_reboot; | ||
32 | } | 31 | } |
33 | 32 | ||
34 | /*-------------------------------------------------------------------------*/ | 33 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index c4c4babd4767..9c02177de50a 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2005 David Brownell | 5 | * (C) Copyright 2000-2005 David Brownell |
6 | * (C) Copyright 2002 Hewlett-Packard Company | 6 | * (C) Copyright 2002 Hewlett-Packard Company |
7 | * | 7 | * |
8 | * OMAP Bus Glue | 8 | * OMAP Bus Glue |
9 | * | 9 | * |
10 | * Modified for OMAP by Tony Lindgren <tony@atomide.com> | 10 | * Modified for OMAP by Tony Lindgren <tony@atomide.com> |
@@ -66,15 +66,20 @@ extern int usb_disabled(void); | |||
66 | extern int ocpi_enable(void); | 66 | extern int ocpi_enable(void); |
67 | 67 | ||
68 | static struct clk *usb_host_ck; | 68 | static struct clk *usb_host_ck; |
69 | static struct clk *usb_dc_ck; | ||
70 | static int host_enabled; | ||
71 | static int host_initialized; | ||
69 | 72 | ||
70 | static void omap_ohci_clock_power(int on) | 73 | static void omap_ohci_clock_power(int on) |
71 | { | 74 | { |
72 | if (on) { | 75 | if (on) { |
76 | clk_enable(usb_dc_ck); | ||
73 | clk_enable(usb_host_ck); | 77 | clk_enable(usb_host_ck); |
74 | /* guesstimate for T5 == 1x 32K clock + APLL lock time */ | 78 | /* guesstimate for T5 == 1x 32K clock + APLL lock time */ |
75 | udelay(100); | 79 | udelay(100); |
76 | } else { | 80 | } else { |
77 | clk_disable(usb_host_ck); | 81 | clk_disable(usb_host_ck); |
82 | clk_disable(usb_dc_ck); | ||
78 | } | 83 | } |
79 | } | 84 | } |
80 | 85 | ||
@@ -87,14 +92,14 @@ static int omap_ohci_transceiver_power(int on) | |||
87 | if (on) { | 92 | if (on) { |
88 | if (machine_is_omap_innovator() && cpu_is_omap1510()) | 93 | if (machine_is_omap_innovator() && cpu_is_omap1510()) |
89 | fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) | 94 | fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) |
90 | | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), | 95 | | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), |
91 | INNOVATOR_FPGA_CAM_USB_CONTROL); | 96 | INNOVATOR_FPGA_CAM_USB_CONTROL); |
92 | else if (machine_is_omap_osk()) | 97 | else if (machine_is_omap_osk()) |
93 | tps65010_set_gpio_out_value(GPIO1, LOW); | 98 | tps65010_set_gpio_out_value(GPIO1, LOW); |
94 | } else { | 99 | } else { |
95 | if (machine_is_omap_innovator() && cpu_is_omap1510()) | 100 | if (machine_is_omap_innovator() && cpu_is_omap1510()) |
96 | fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) | 101 | fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) |
97 | & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), | 102 | & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), |
98 | INNOVATOR_FPGA_CAM_USB_CONTROL); | 103 | INNOVATOR_FPGA_CAM_USB_CONTROL); |
99 | else if (machine_is_omap_osk()) | 104 | else if (machine_is_omap_osk()) |
100 | tps65010_set_gpio_out_value(GPIO1, HIGH); | 105 | tps65010_set_gpio_out_value(GPIO1, HIGH); |
@@ -103,6 +108,7 @@ static int omap_ohci_transceiver_power(int on) | |||
103 | return 0; | 108 | return 0; |
104 | } | 109 | } |
105 | 110 | ||
111 | #ifdef CONFIG_ARCH_OMAP15XX | ||
106 | /* | 112 | /* |
107 | * OMAP-1510 specific Local Bus clock on/off | 113 | * OMAP-1510 specific Local Bus clock on/off |
108 | */ | 114 | */ |
@@ -121,8 +127,8 @@ static int omap_1510_local_bus_power(int on) | |||
121 | /* | 127 | /* |
122 | * OMAP-1510 specific Local Bus initialization | 128 | * OMAP-1510 specific Local Bus initialization |
123 | * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE. | 129 | * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE. |
124 | * See also arch/mach-omap/memory.h for __virt_to_dma() and | 130 | * See also arch/mach-omap/memory.h for __virt_to_dma() and |
125 | * __dma_to_virt() which need to match with the physical | 131 | * __dma_to_virt() which need to match with the physical |
126 | * Local Bus address below. | 132 | * Local Bus address below. |
127 | */ | 133 | */ |
128 | static int omap_1510_local_bus_init(void) | 134 | static int omap_1510_local_bus_init(void) |
@@ -130,7 +136,7 @@ static int omap_1510_local_bus_init(void) | |||
130 | unsigned int tlb; | 136 | unsigned int tlb; |
131 | unsigned long lbaddr, physaddr; | 137 | unsigned long lbaddr, physaddr; |
132 | 138 | ||
133 | omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, | 139 | omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, |
134 | OMAP1510_LB_CLOCK_DIV); | 140 | OMAP1510_LB_CLOCK_DIV); |
135 | 141 | ||
136 | /* Configure the Local Bus MMU table */ | 142 | /* Configure the Local Bus MMU table */ |
@@ -138,7 +144,7 @@ static int omap_1510_local_bus_init(void) | |||
138 | lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET; | 144 | lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET; |
139 | physaddr = tlb * 0x00100000 + PHYS_OFFSET; | 145 | physaddr = tlb * 0x00100000 + PHYS_OFFSET; |
140 | omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H); | 146 | omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H); |
141 | omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, | 147 | omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, |
142 | OMAP1510_LB_MMU_CAM_L); | 148 | OMAP1510_LB_MMU_CAM_L); |
143 | omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H); | 149 | omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H); |
144 | omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L); | 150 | omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L); |
@@ -152,6 +158,10 @@ static int omap_1510_local_bus_init(void) | |||
152 | 158 | ||
153 | return 0; | 159 | return 0; |
154 | } | 160 | } |
161 | #else | ||
162 | #define omap_1510_local_bus_power(x) {} | ||
163 | #define omap_1510_local_bus_init() {} | ||
164 | #endif | ||
155 | 165 | ||
156 | #ifdef CONFIG_USB_OTG | 166 | #ifdef CONFIG_USB_OTG |
157 | 167 | ||
@@ -173,13 +183,14 @@ static void start_hnp(struct ohci_hcd *ohci) | |||
173 | 183 | ||
174 | /*-------------------------------------------------------------------------*/ | 184 | /*-------------------------------------------------------------------------*/ |
175 | 185 | ||
176 | static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | 186 | static int ohci_omap_init(struct usb_hcd *hcd) |
177 | { | 187 | { |
178 | struct omap_usb_config *config = pdev->dev.platform_data; | 188 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
189 | struct omap_usb_config *config = hcd->self.controller->platform_data; | ||
179 | int need_transceiver = (config->otg != 0); | 190 | int need_transceiver = (config->otg != 0); |
180 | int ret; | 191 | int ret; |
181 | 192 | ||
182 | dev_dbg(&pdev->dev, "starting USB Controller\n"); | 193 | dev_dbg(hcd->self.controller, "starting USB Controller\n"); |
183 | 194 | ||
184 | if (config->otg) { | 195 | if (config->otg) { |
185 | ohci_to_hcd(ohci)->self.otg_port = config->otg; | 196 | ohci_to_hcd(ohci)->self.otg_port = config->otg; |
@@ -200,7 +211,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
200 | if (ohci->transceiver) { | 211 | if (ohci->transceiver) { |
201 | int status = otg_set_host(ohci->transceiver, | 212 | int status = otg_set_host(ohci->transceiver, |
202 | &ohci_to_hcd(ohci)->self); | 213 | &ohci_to_hcd(ohci)->self); |
203 | dev_dbg(&pdev->dev, "init %s transceiver, status %d\n", | 214 | dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n", |
204 | ohci->transceiver->label, status); | 215 | ohci->transceiver->label, status); |
205 | if (status) { | 216 | if (status) { |
206 | if (ohci->transceiver) | 217 | if (ohci->transceiver) |
@@ -208,7 +219,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
208 | return status; | 219 | return status; |
209 | } | 220 | } |
210 | } else { | 221 | } else { |
211 | dev_err(&pdev->dev, "can't find transceiver\n"); | 222 | dev_err(hcd->self.controller, "can't find transceiver\n"); |
212 | return -ENODEV; | 223 | return -ENODEV; |
213 | } | 224 | } |
214 | } | 225 | } |
@@ -247,6 +258,10 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
247 | } | 258 | } |
248 | ohci_writel(ohci, rh, &ohci->regs->roothub.a); | 259 | ohci_writel(ohci, rh, &ohci->regs->roothub.a); |
249 | distrust_firmware = 0; | 260 | distrust_firmware = 0; |
261 | } else if (machine_is_nokia770()) { | ||
262 | /* We require a self-powered hub, which should have | ||
263 | * plenty of power. */ | ||
264 | ohci_to_hcd(ohci)->power_budget = 0; | ||
250 | } | 265 | } |
251 | 266 | ||
252 | /* FIXME khubd hub requests should manage power switching */ | 267 | /* FIXME khubd hub requests should manage power switching */ |
@@ -260,21 +275,15 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
260 | return 0; | 275 | return 0; |
261 | } | 276 | } |
262 | 277 | ||
263 | static void omap_stop_hc(struct platform_device *pdev) | 278 | static void ohci_omap_stop(struct usb_hcd *hcd) |
264 | { | 279 | { |
265 | dev_dbg(&pdev->dev, "stopping USB Controller\n"); | 280 | dev_dbg(hcd->self.controller, "stopping USB Controller\n"); |
266 | omap_ohci_clock_power(0); | 281 | omap_ohci_clock_power(0); |
267 | } | 282 | } |
268 | 283 | ||
269 | 284 | ||
270 | /*-------------------------------------------------------------------------*/ | 285 | /*-------------------------------------------------------------------------*/ |
271 | 286 | ||
272 | void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *); | ||
273 | |||
274 | /* configure so an HC device and id are always provided */ | ||
275 | /* always called with process context; sleeping is OK */ | ||
276 | |||
277 | |||
278 | /** | 287 | /** |
279 | * usb_hcd_omap_probe - initialize OMAP-based HCDs | 288 | * usb_hcd_omap_probe - initialize OMAP-based HCDs |
280 | * Context: !in_interrupt() | 289 | * Context: !in_interrupt() |
@@ -283,7 +292,7 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *); | |||
283 | * then invokes the start() method for the HCD associated with it | 292 | * then invokes the start() method for the HCD associated with it |
284 | * through the hotplug entry's driver_data. | 293 | * through the hotplug entry's driver_data. |
285 | */ | 294 | */ |
286 | int usb_hcd_omap_probe (const struct hc_driver *driver, | 295 | static int usb_hcd_omap_probe (const struct hc_driver *driver, |
287 | struct platform_device *pdev) | 296 | struct platform_device *pdev) |
288 | { | 297 | { |
289 | int retval, irq; | 298 | int retval, irq; |
@@ -291,12 +300,12 @@ int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
291 | struct ohci_hcd *ohci; | 300 | struct ohci_hcd *ohci; |
292 | 301 | ||
293 | if (pdev->num_resources != 2) { | 302 | if (pdev->num_resources != 2) { |
294 | printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", | 303 | printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", |
295 | pdev->num_resources); | 304 | pdev->num_resources); |
296 | return -ENODEV; | 305 | return -ENODEV; |
297 | } | 306 | } |
298 | 307 | ||
299 | if (pdev->resource[0].flags != IORESOURCE_MEM | 308 | if (pdev->resource[0].flags != IORESOURCE_MEM |
300 | || pdev->resource[1].flags != IORESOURCE_IRQ) { | 309 | || pdev->resource[1].flags != IORESOURCE_IRQ) { |
301 | printk(KERN_ERR "hcd probe: invalid resource type\n"); | 310 | printk(KERN_ERR "hcd probe: invalid resource type\n"); |
302 | return -ENODEV; | 311 | return -ENODEV; |
@@ -306,6 +315,17 @@ int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
306 | if (IS_ERR(usb_host_ck)) | 315 | if (IS_ERR(usb_host_ck)) |
307 | return PTR_ERR(usb_host_ck); | 316 | return PTR_ERR(usb_host_ck); |
308 | 317 | ||
318 | if (!cpu_is_omap1510()) | ||
319 | usb_dc_ck = clk_get(0, "usb_dc_ck"); | ||
320 | else | ||
321 | usb_dc_ck = clk_get(0, "lb_ck"); | ||
322 | |||
323 | if (IS_ERR(usb_dc_ck)) { | ||
324 | clk_put(usb_host_ck); | ||
325 | return PTR_ERR(usb_dc_ck); | ||
326 | } | ||
327 | |||
328 | |||
309 | hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); | 329 | hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); |
310 | if (!hcd) { | 330 | if (!hcd) { |
311 | retval = -ENOMEM; | 331 | retval = -ENOMEM; |
@@ -325,9 +345,8 @@ int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
325 | ohci = hcd_to_ohci(hcd); | 345 | ohci = hcd_to_ohci(hcd); |
326 | ohci_hcd_init(ohci); | 346 | ohci_hcd_init(ohci); |
327 | 347 | ||
328 | retval = omap_start_hc(ohci, pdev); | 348 | host_initialized = 0; |
329 | if (retval < 0) | 349 | host_enabled = 1; |
330 | goto err2; | ||
331 | 350 | ||
332 | irq = platform_get_irq(pdev, 0); | 351 | irq = platform_get_irq(pdev, 0); |
333 | if (irq < 0) { | 352 | if (irq < 0) { |
@@ -335,15 +354,21 @@ int usb_hcd_omap_probe (const struct hc_driver *driver, | |||
335 | goto err2; | 354 | goto err2; |
336 | } | 355 | } |
337 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | 356 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); |
338 | if (retval == 0) | 357 | if (retval) |
339 | return retval; | 358 | goto err2; |
359 | |||
360 | host_initialized = 1; | ||
361 | |||
362 | if (!host_enabled) | ||
363 | omap_ohci_clock_power(0); | ||
340 | 364 | ||
341 | omap_stop_hc(pdev); | 365 | return 0; |
342 | err2: | 366 | err2: |
343 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 367 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
344 | err1: | 368 | err1: |
345 | usb_put_hcd(hcd); | 369 | usb_put_hcd(hcd); |
346 | err0: | 370 | err0: |
371 | clk_put(usb_dc_ck); | ||
347 | clk_put(usb_host_ck); | 372 | clk_put(usb_host_ck); |
348 | return retval; | 373 | return retval; |
349 | } | 374 | } |
@@ -359,31 +384,41 @@ err0: | |||
359 | * Reverses the effect of usb_hcd_omap_probe(), first invoking | 384 | * Reverses the effect of usb_hcd_omap_probe(), first invoking |
360 | * the HCD's stop() method. It is always called from a thread | 385 | * the HCD's stop() method. It is always called from a thread |
361 | * context, normally "rmmod", "apmd", or something similar. | 386 | * context, normally "rmmod", "apmd", or something similar. |
362 | * | ||
363 | */ | 387 | */ |
364 | void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) | 388 | static inline void |
389 | usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) | ||
365 | { | 390 | { |
391 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
392 | |||
366 | usb_remove_hcd(hcd); | 393 | usb_remove_hcd(hcd); |
394 | if (ohci->transceiver) { | ||
395 | (void) otg_set_host(ohci->transceiver, 0); | ||
396 | put_device(ohci->transceiver->dev); | ||
397 | } | ||
367 | if (machine_is_omap_osk()) | 398 | if (machine_is_omap_osk()) |
368 | omap_free_gpio(9); | 399 | omap_free_gpio(9); |
369 | omap_stop_hc(pdev); | ||
370 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 400 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
371 | usb_put_hcd(hcd); | 401 | usb_put_hcd(hcd); |
402 | clk_put(usb_dc_ck); | ||
372 | clk_put(usb_host_ck); | 403 | clk_put(usb_host_ck); |
373 | } | 404 | } |
374 | 405 | ||
375 | /*-------------------------------------------------------------------------*/ | 406 | /*-------------------------------------------------------------------------*/ |
376 | 407 | ||
377 | static int __devinit | 408 | static int |
378 | ohci_omap_start (struct usb_hcd *hcd) | 409 | ohci_omap_start (struct usb_hcd *hcd) |
379 | { | 410 | { |
380 | struct omap_usb_config *config; | 411 | struct omap_usb_config *config; |
381 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 412 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
382 | int ret; | 413 | int ret; |
383 | 414 | ||
415 | if (!host_enabled) | ||
416 | return 0; | ||
384 | config = hcd->self.controller->platform_data; | 417 | config = hcd->self.controller->platform_data; |
385 | if (config->otg || config->rwc) | 418 | if (config->otg || config->rwc) { |
419 | ohci->hc_control = OHCI_CTRL_RWC; | ||
386 | writel(OHCI_CTRL_RWC, &ohci->regs->control); | 420 | writel(OHCI_CTRL_RWC, &ohci->regs->control); |
421 | } | ||
387 | 422 | ||
388 | if ((ret = ohci_run (ohci)) < 0) { | 423 | if ((ret = ohci_run (ohci)) < 0) { |
389 | dev_err(hcd->self.controller, "can't start\n"); | 424 | dev_err(hcd->self.controller, "can't start\n"); |
@@ -409,8 +444,10 @@ static const struct hc_driver ohci_omap_hc_driver = { | |||
409 | /* | 444 | /* |
410 | * basic lifecycle operations | 445 | * basic lifecycle operations |
411 | */ | 446 | */ |
447 | .reset = ohci_omap_init, | ||
412 | .start = ohci_omap_start, | 448 | .start = ohci_omap_start, |
413 | .stop = ohci_stop, | 449 | .stop = ohci_omap_stop, |
450 | .shutdown = ohci_shutdown, | ||
414 | 451 | ||
415 | /* | 452 | /* |
416 | * managing i/o requests and associated device resources | 453 | * managing i/o requests and associated device resources |
@@ -429,6 +466,7 @@ static const struct hc_driver ohci_omap_hc_driver = { | |||
429 | */ | 466 | */ |
430 | .hub_status_data = ohci_hub_status_data, | 467 | .hub_status_data = ohci_hub_status_data, |
431 | .hub_control = ohci_hub_control, | 468 | .hub_control = ohci_hub_control, |
469 | .hub_irq_enable = ohci_rhsc_enable, | ||
432 | #ifdef CONFIG_PM | 470 | #ifdef CONFIG_PM |
433 | .bus_suspend = ohci_bus_suspend, | 471 | .bus_suspend = ohci_bus_suspend, |
434 | .bus_resume = ohci_bus_resume, | 472 | .bus_resume = ohci_bus_resume, |
@@ -446,13 +484,8 @@ static int ohci_hcd_omap_drv_probe(struct platform_device *dev) | |||
446 | static int ohci_hcd_omap_drv_remove(struct platform_device *dev) | 484 | static int ohci_hcd_omap_drv_remove(struct platform_device *dev) |
447 | { | 485 | { |
448 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 486 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
449 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
450 | 487 | ||
451 | usb_hcd_omap_remove(hcd, dev); | 488 | usb_hcd_omap_remove(hcd, dev); |
452 | if (ohci->transceiver) { | ||
453 | (void) otg_set_host(ohci->transceiver, 0); | ||
454 | put_device(ohci->transceiver->dev); | ||
455 | } | ||
456 | platform_set_drvdata(dev, NULL); | 489 | platform_set_drvdata(dev, NULL); |
457 | 490 | ||
458 | return 0; | 491 | return 0; |
@@ -472,7 +505,7 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message) | |||
472 | 505 | ||
473 | omap_ohci_clock_power(0); | 506 | omap_ohci_clock_power(0); |
474 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; | 507 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; |
475 | dev->power.power_state = PMSG_SUSPEND; | 508 | dev->dev.power.power_state = PMSG_SUSPEND; |
476 | return 0; | 509 | return 0; |
477 | } | 510 | } |
478 | 511 | ||
@@ -485,8 +518,8 @@ static int ohci_omap_resume(struct platform_device *dev) | |||
485 | ohci->next_statechange = jiffies; | 518 | ohci->next_statechange = jiffies; |
486 | 519 | ||
487 | omap_ohci_clock_power(1); | 520 | omap_ohci_clock_power(1); |
488 | dev->power.power_state = PMSG_ON; | 521 | dev->dev.power.power_state = PMSG_ON; |
489 | usb_hcd_resume_root_hub(dev_get_drvdata(dev)); | 522 | usb_hcd_resume_root_hub(platform_get_drvdata(dev)); |
490 | return 0; | 523 | return 0; |
491 | } | 524 | } |
492 | 525 | ||
@@ -500,6 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev) | |||
500 | static struct platform_driver ohci_hcd_omap_driver = { | 533 | static struct platform_driver ohci_hcd_omap_driver = { |
501 | .probe = ohci_hcd_omap_drv_probe, | 534 | .probe = ohci_hcd_omap_drv_probe, |
502 | .remove = ohci_hcd_omap_drv_remove, | 535 | .remove = ohci_hcd_omap_drv_remove, |
536 | .shutdown = usb_hcd_platform_shutdown, | ||
503 | #ifdef CONFIG_PM | 537 | #ifdef CONFIG_PM |
504 | .suspend = ohci_omap_suspend, | 538 | .suspend = ohci_omap_suspend, |
505 | .resume = ohci_omap_resume, | 539 | .resume = ohci_omap_resume, |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index b268537e389e..3732db7d68eb 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -135,6 +135,11 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
135 | } | 135 | } |
136 | ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 136 | ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
137 | (void)ohci_readl(ohci, &ohci->regs->intrdisable); | 137 | (void)ohci_readl(ohci, &ohci->regs->intrdisable); |
138 | |||
139 | /* make sure snapshot being resumed re-enumerates everything */ | ||
140 | if (message.event == PM_EVENT_PRETHAW) | ||
141 | ohci_usb_reset(ohci); | ||
142 | |||
138 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 143 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
139 | bail: | 144 | bail: |
140 | spin_unlock_irqrestore (&ohci->lock, flags); | 145 | spin_unlock_irqrestore (&ohci->lock, flags); |
@@ -171,11 +176,14 @@ static const struct hc_driver ohci_pci_hc_driver = { | |||
171 | */ | 176 | */ |
172 | .reset = ohci_pci_reset, | 177 | .reset = ohci_pci_reset, |
173 | .start = ohci_pci_start, | 178 | .start = ohci_pci_start, |
179 | .stop = ohci_stop, | ||
180 | .shutdown = ohci_shutdown, | ||
181 | |||
174 | #ifdef CONFIG_PM | 182 | #ifdef CONFIG_PM |
183 | /* these suspend/resume entries are for upstream PCI glue ONLY */ | ||
175 | .suspend = ohci_pci_suspend, | 184 | .suspend = ohci_pci_suspend, |
176 | .resume = ohci_pci_resume, | 185 | .resume = ohci_pci_resume, |
177 | #endif | 186 | #endif |
178 | .stop = ohci_stop, | ||
179 | 187 | ||
180 | /* | 188 | /* |
181 | * managing i/o requests and associated device resources | 189 | * managing i/o requests and associated device resources |
@@ -194,6 +202,7 @@ static const struct hc_driver ohci_pci_hc_driver = { | |||
194 | */ | 202 | */ |
195 | .hub_status_data = ohci_hub_status_data, | 203 | .hub_status_data = ohci_hub_status_data, |
196 | .hub_control = ohci_hub_control, | 204 | .hub_control = ohci_hub_control, |
205 | .hub_irq_enable = ohci_rhsc_enable, | ||
197 | #ifdef CONFIG_PM | 206 | #ifdef CONFIG_PM |
198 | .bus_suspend = ohci_bus_suspend, | 207 | .bus_suspend = ohci_bus_suspend, |
199 | .bus_resume = ohci_bus_resume, | 208 | .bus_resume = ohci_bus_resume, |
@@ -224,6 +233,8 @@ static struct pci_driver ohci_pci_driver = { | |||
224 | .suspend = usb_hcd_pci_suspend, | 233 | .suspend = usb_hcd_pci_suspend, |
225 | .resume = usb_hcd_pci_resume, | 234 | .resume = usb_hcd_pci_resume, |
226 | #endif | 235 | #endif |
236 | |||
237 | .shutdown = usb_hcd_pci_shutdown, | ||
227 | }; | 238 | }; |
228 | 239 | ||
229 | 240 | ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c new file mode 100644 index 000000000000..82cb22f002e7 --- /dev/null +++ b/drivers/usb/host/ohci-pnx4008.c | |||
@@ -0,0 +1,476 @@ | |||
1 | /* | ||
2 | * drivers/usb/host/ohci-pnx4008.c | ||
3 | * | ||
4 | * driver for Philips PNX4008 USB Host | ||
5 | * | ||
6 | * Authors: Dmitry Chigirev <source@mvista.com> | ||
7 | * Vitaly Wool <vitalywool@gmail.com> | ||
8 | * | ||
9 | * register initialization is based on code examples provided by Philips | ||
10 | * Copyright (c) 2005 Koninklijke Philips Electronics N.V. | ||
11 | * | ||
12 | * NOTE: This driver does not have suspend/resume functionality | ||
13 | * This driver is intended for engineering development purposes only | ||
14 | * | ||
15 | * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under | ||
16 | * the terms of the GNU General Public License version 2. This program | ||
17 | * is licensed "as is" without any warranty of any kind, whether express | ||
18 | * or implied. | ||
19 | */ | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/i2c.h> | ||
23 | |||
24 | #include <asm/hardware.h> | ||
25 | #include <asm/io.h> | ||
26 | #include <asm/mach-types.h> | ||
27 | |||
28 | #include <asm/arch/platform.h> | ||
29 | #include <asm/arch/irqs.h> | ||
30 | #include <asm/arch/gpio.h> | ||
31 | |||
32 | #define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64) | ||
33 | |||
34 | /* USB_CTRL bit defines */ | ||
35 | #define USB_SLAVE_HCLK_EN (1 << 24) | ||
36 | #define USB_HOST_NEED_CLK_EN (1 << 21) | ||
37 | |||
38 | #define USB_OTG_CLK_CTRL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4) | ||
39 | #define USB_OTG_CLK_STAT IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8) | ||
40 | |||
41 | /* USB_OTG_CLK_CTRL bit defines */ | ||
42 | #define AHB_M_CLOCK_ON (1 << 4) | ||
43 | #define OTG_CLOCK_ON (1 << 3) | ||
44 | #define I2C_CLOCK_ON (1 << 2) | ||
45 | #define DEV_CLOCK_ON (1 << 1) | ||
46 | #define HOST_CLOCK_ON (1 << 0) | ||
47 | |||
48 | #define USB_OTG_STAT_CONTROL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110) | ||
49 | |||
50 | /* USB_OTG_STAT_CONTROL bit defines */ | ||
51 | #define TRANSPARENT_I2C_EN (1 << 7) | ||
52 | #define HOST_EN (1 << 0) | ||
53 | |||
54 | /* ISP1301 USB transceiver I2C registers */ | ||
55 | #define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */ | ||
56 | |||
57 | #define MC1_SPEED_REG (1 << 0) | ||
58 | #define MC1_SUSPEND_REG (1 << 1) | ||
59 | #define MC1_DAT_SE0 (1 << 2) | ||
60 | #define MC1_TRANSPARENT (1 << 3) | ||
61 | #define MC1_BDIS_ACON_EN (1 << 4) | ||
62 | #define MC1_OE_INT_EN (1 << 5) | ||
63 | #define MC1_UART_EN (1 << 6) | ||
64 | #define MC1_MASK 0x7f | ||
65 | |||
66 | #define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */ | ||
67 | |||
68 | #define MC2_GLOBAL_PWR_DN (1 << 0) | ||
69 | #define MC2_SPD_SUSP_CTRL (1 << 1) | ||
70 | #define MC2_BI_DI (1 << 2) | ||
71 | #define MC2_TRANSP_BDIR0 (1 << 3) | ||
72 | #define MC2_TRANSP_BDIR1 (1 << 4) | ||
73 | #define MC2_AUDIO_EN (1 << 5) | ||
74 | #define MC2_PSW_EN (1 << 6) | ||
75 | #define MC2_EN2V7 (1 << 7) | ||
76 | |||
77 | #define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */ | ||
78 | # define OTG1_DP_PULLUP (1 << 0) | ||
79 | # define OTG1_DM_PULLUP (1 << 1) | ||
80 | # define OTG1_DP_PULLDOWN (1 << 2) | ||
81 | # define OTG1_DM_PULLDOWN (1 << 3) | ||
82 | # define OTG1_ID_PULLDOWN (1 << 4) | ||
83 | # define OTG1_VBUS_DRV (1 << 5) | ||
84 | # define OTG1_VBUS_DISCHRG (1 << 6) | ||
85 | # define OTG1_VBUS_CHRG (1 << 7) | ||
86 | #define ISP1301_OTG_STATUS 0x10 /* u8 readonly */ | ||
87 | # define OTG_B_SESS_END (1 << 6) | ||
88 | # define OTG_B_SESS_VLD (1 << 7) | ||
89 | |||
90 | #define ISP1301_I2C_ADDR 0x2C | ||
91 | |||
92 | #define ISP1301_I2C_MODE_CONTROL_1 0x4 | ||
93 | #define ISP1301_I2C_MODE_CONTROL_2 0x12 | ||
94 | #define ISP1301_I2C_OTG_CONTROL_1 0x6 | ||
95 | #define ISP1301_I2C_OTG_CONTROL_2 0x10 | ||
96 | #define ISP1301_I2C_INTERRUPT_SOURCE 0x8 | ||
97 | #define ISP1301_I2C_INTERRUPT_LATCH 0xA | ||
98 | #define ISP1301_I2C_INTERRUPT_FALLING 0xC | ||
99 | #define ISP1301_I2C_INTERRUPT_RISING 0xE | ||
100 | #define ISP1301_I2C_REG_CLEAR_ADDR 1 | ||
101 | |||
102 | struct i2c_driver isp1301_driver; | ||
103 | struct i2c_client *isp1301_i2c_client; | ||
104 | |||
105 | extern int usb_disabled(void); | ||
106 | extern int ocpi_enable(void); | ||
107 | |||
108 | static struct clk *usb_clk; | ||
109 | |||
110 | static int isp1301_probe(struct i2c_adapter *adap); | ||
111 | static int isp1301_detach(struct i2c_client *client); | ||
112 | static int isp1301_command(struct i2c_client *client, unsigned int cmd, | ||
113 | void *arg); | ||
114 | |||
115 | static unsigned short normal_i2c[] = | ||
116 | { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; | ||
117 | static unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END }; | ||
118 | |||
119 | static struct i2c_client_address_data addr_data = { | ||
120 | .normal_i2c = normal_i2c, | ||
121 | .probe = dummy_i2c_addrlist, | ||
122 | .ignore = dummy_i2c_addrlist, | ||
123 | }; | ||
124 | |||
125 | struct i2c_driver isp1301_driver = { | ||
126 | .id = I2C_DRIVERID_I2CDEV, /* Fake Id */ | ||
127 | .class = I2C_CLASS_HWMON, | ||
128 | .attach_adapter = isp1301_probe, | ||
129 | .detach_client = isp1301_detach, | ||
130 | .command = isp1301_command | ||
131 | }; | ||
132 | |||
133 | static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind) | ||
134 | { | ||
135 | struct i2c_client *c; | ||
136 | |||
137 | c = (struct i2c_client *)kzalloc(sizeof(*c), SLAB_KERNEL); | ||
138 | |||
139 | if (!c) | ||
140 | return -ENOMEM; | ||
141 | |||
142 | strcpy(c->name, "isp1301"); | ||
143 | c->flags = 0; | ||
144 | c->addr = addr; | ||
145 | c->adapter = adap; | ||
146 | c->driver = &isp1301_driver; | ||
147 | |||
148 | isp1301_i2c_client = c; | ||
149 | |||
150 | return i2c_attach_client(c); | ||
151 | } | ||
152 | |||
153 | static int isp1301_probe(struct i2c_adapter *adap) | ||
154 | { | ||
155 | return i2c_probe(adap, &addr_data, isp1301_attach); | ||
156 | } | ||
157 | |||
158 | static int isp1301_detach(struct i2c_client *client) | ||
159 | { | ||
160 | i2c_detach_client(client); | ||
161 | kfree(isp1301_i2c_client); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /* No commands defined */ | ||
166 | static int isp1301_command(struct i2c_client *client, unsigned int cmd, | ||
167 | void *arg) | ||
168 | { | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static void i2c_write(u8 buf, u8 subaddr) | ||
173 | { | ||
174 | char tmpbuf[2]; | ||
175 | |||
176 | tmpbuf[0] = subaddr; /*register number */ | ||
177 | tmpbuf[1] = buf; /*register data */ | ||
178 | i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2); | ||
179 | } | ||
180 | |||
181 | static void isp1301_configure(void) | ||
182 | { | ||
183 | /* PNX4008 only supports DAT_SE0 USB mode */ | ||
184 | /* PNX4008 R2A requires setting the MAX603 to output 3.6V */ | ||
185 | /* Power up externel charge-pump */ | ||
186 | |||
187 | i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1); | ||
188 | i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG), | ||
189 | ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
190 | i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL, | ||
191 | ISP1301_I2C_MODE_CONTROL_2); | ||
192 | i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL), | ||
193 | ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
194 | i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN, | ||
195 | ISP1301_I2C_OTG_CONTROL_1); | ||
196 | i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN), | ||
197 | ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
198 | i2c_write(0xFF, | ||
199 | ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR); | ||
200 | i2c_write(0xFF, | ||
201 | ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR); | ||
202 | i2c_write(0xFF, | ||
203 | ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR); | ||
204 | |||
205 | } | ||
206 | |||
207 | static inline void isp1301_vbus_on(void) | ||
208 | { | ||
209 | i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1); | ||
210 | } | ||
211 | |||
212 | static inline void isp1301_vbus_off(void) | ||
213 | { | ||
214 | i2c_write(OTG1_VBUS_DRV, | ||
215 | ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); | ||
216 | } | ||
217 | |||
218 | static void pnx4008_start_hc(void) | ||
219 | { | ||
220 | unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN; | ||
221 | __raw_writel(tmp, USB_OTG_STAT_CONTROL); | ||
222 | isp1301_vbus_on(); | ||
223 | } | ||
224 | |||
225 | static void pnx4008_stop_hc(void) | ||
226 | { | ||
227 | unsigned long tmp; | ||
228 | isp1301_vbus_off(); | ||
229 | tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN; | ||
230 | __raw_writel(tmp, USB_OTG_STAT_CONTROL); | ||
231 | } | ||
232 | |||
233 | static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd) | ||
234 | { | ||
235 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
236 | int ret; | ||
237 | |||
238 | if ((ret = ohci_init(ohci)) < 0) | ||
239 | return ret; | ||
240 | |||
241 | if ((ret = ohci_run(ohci)) < 0) { | ||
242 | dev_err(hcd->self.controller, "can't start\n"); | ||
243 | ohci_stop(hcd); | ||
244 | return ret; | ||
245 | } | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static const struct hc_driver ohci_pnx4008_hc_driver = { | ||
250 | .description = hcd_name, | ||
251 | .product_desc = "pnx4008 OHCI", | ||
252 | |||
253 | /* | ||
254 | * generic hardware linkage | ||
255 | */ | ||
256 | .irq = ohci_irq, | ||
257 | .flags = HCD_USB11 | HCD_MEMORY, | ||
258 | |||
259 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
260 | /* | ||
261 | * basic lifecycle operations | ||
262 | */ | ||
263 | .start = ohci_pnx4008_start, | ||
264 | .stop = ohci_stop, | ||
265 | |||
266 | /* | ||
267 | * managing i/o requests and associated device resources | ||
268 | */ | ||
269 | .urb_enqueue = ohci_urb_enqueue, | ||
270 | .urb_dequeue = ohci_urb_dequeue, | ||
271 | .endpoint_disable = ohci_endpoint_disable, | ||
272 | |||
273 | /* | ||
274 | * scheduling support | ||
275 | */ | ||
276 | .get_frame_number = ohci_get_frame, | ||
277 | |||
278 | /* | ||
279 | * root hub support | ||
280 | */ | ||
281 | .hub_status_data = ohci_hub_status_data, | ||
282 | .hub_control = ohci_hub_control, | ||
283 | |||
284 | .start_port_reset = ohci_start_port_reset, | ||
285 | }; | ||
286 | |||
287 | #define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON) | ||
288 | |||
289 | static void pnx4008_set_usb_bits(void) | ||
290 | { | ||
291 | start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N); | ||
292 | start_int_ack(SE_USB_OTG_ATX_INT_N); | ||
293 | start_int_umask(SE_USB_OTG_ATX_INT_N); | ||
294 | |||
295 | start_int_set_rising_edge(SE_USB_OTG_TIMER_INT); | ||
296 | start_int_ack(SE_USB_OTG_TIMER_INT); | ||
297 | start_int_umask(SE_USB_OTG_TIMER_INT); | ||
298 | |||
299 | start_int_set_rising_edge(SE_USB_I2C_INT); | ||
300 | start_int_ack(SE_USB_I2C_INT); | ||
301 | start_int_umask(SE_USB_I2C_INT); | ||
302 | |||
303 | start_int_set_rising_edge(SE_USB_INT); | ||
304 | start_int_ack(SE_USB_INT); | ||
305 | start_int_umask(SE_USB_INT); | ||
306 | |||
307 | start_int_set_rising_edge(SE_USB_NEED_CLK_INT); | ||
308 | start_int_ack(SE_USB_NEED_CLK_INT); | ||
309 | start_int_umask(SE_USB_NEED_CLK_INT); | ||
310 | |||
311 | start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT); | ||
312 | start_int_ack(SE_USB_AHB_NEED_CLK_INT); | ||
313 | start_int_umask(SE_USB_AHB_NEED_CLK_INT); | ||
314 | } | ||
315 | |||
316 | static void pnx4008_unset_usb_bits(void) | ||
317 | { | ||
318 | start_int_mask(SE_USB_OTG_ATX_INT_N); | ||
319 | start_int_mask(SE_USB_OTG_TIMER_INT); | ||
320 | start_int_mask(SE_USB_I2C_INT); | ||
321 | start_int_mask(SE_USB_INT); | ||
322 | start_int_mask(SE_USB_NEED_CLK_INT); | ||
323 | start_int_mask(SE_USB_AHB_NEED_CLK_INT); | ||
324 | } | ||
325 | |||
326 | static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) | ||
327 | { | ||
328 | struct usb_hcd *hcd = 0; | ||
329 | struct ohci_hcd *ohci; | ||
330 | const struct hc_driver *driver = &ohci_pnx4008_hc_driver; | ||
331 | |||
332 | int ret = 0, irq; | ||
333 | |||
334 | dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name); | ||
335 | if (usb_disabled()) { | ||
336 | err("USB is disabled"); | ||
337 | ret = -ENODEV; | ||
338 | goto out; | ||
339 | } | ||
340 | |||
341 | if (pdev->num_resources != 2 | ||
342 | || pdev->resource[0].flags != IORESOURCE_MEM | ||
343 | || pdev->resource[1].flags != IORESOURCE_IRQ) { | ||
344 | err("Invalid resource configuration"); | ||
345 | ret = -ENODEV; | ||
346 | goto out; | ||
347 | } | ||
348 | |||
349 | /* Enable AHB slave USB clock, needed for further USB clock control */ | ||
350 | __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL); | ||
351 | |||
352 | ret = i2c_add_driver(&isp1301_driver); | ||
353 | if (ret < 0) { | ||
354 | err("failed to connect I2C to ISP1301 USB Transceiver"); | ||
355 | goto out; | ||
356 | } | ||
357 | |||
358 | isp1301_configure(); | ||
359 | |||
360 | /* Enable USB PLL */ | ||
361 | usb_clk = clk_get(&pdev->dev, "ck_pll5"); | ||
362 | if (IS_ERR(usb_clk)) { | ||
363 | err("failed to acquire USB PLL"); | ||
364 | ret = PTR_ERR(usb_clk); | ||
365 | goto out1; | ||
366 | } | ||
367 | |||
368 | ret = clk_enable(usb_clk); | ||
369 | if (ret < 0) { | ||
370 | err("failed to start USB PLL"); | ||
371 | goto out2; | ||
372 | } | ||
373 | |||
374 | ret = clk_set_rate(usb_clk, 48000); | ||
375 | if (ret < 0) { | ||
376 | err("failed to set USB clock rate"); | ||
377 | goto out3; | ||
378 | } | ||
379 | |||
380 | __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL); | ||
381 | |||
382 | /* Set to enable all needed USB clocks */ | ||
383 | __raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL); | ||
384 | |||
385 | while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) != | ||
386 | USB_CLOCK_MASK) ; | ||
387 | |||
388 | hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); | ||
389 | if (!hcd) { | ||
390 | err("Failed to allocate HC buffer"); | ||
391 | ret = -ENOMEM; | ||
392 | goto out3; | ||
393 | } | ||
394 | |||
395 | /* Set all USB bits in the Start Enable register */ | ||
396 | pnx4008_set_usb_bits(); | ||
397 | |||
398 | hcd->rsrc_start = pdev->resource[0].start; | ||
399 | hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; | ||
400 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
401 | dev_dbg(&pdev->dev, "request_mem_region failed\n"); | ||
402 | ret = -ENOMEM; | ||
403 | goto out4; | ||
404 | } | ||
405 | hcd->regs = (void __iomem *)pdev->resource[0].start; | ||
406 | |||
407 | irq = platform_get_irq(pdev, 0); | ||
408 | if (irq < 0) { | ||
409 | ret = -ENXIO; | ||
410 | goto out4; | ||
411 | } | ||
412 | |||
413 | hcd->self.hcpriv = (void *)hcd; | ||
414 | |||
415 | pnx4008_start_hc(); | ||
416 | platform_set_drvdata(pdev, hcd); | ||
417 | ohci = hcd_to_ohci(hcd); | ||
418 | ohci_hcd_init(ohci); | ||
419 | |||
420 | dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq); | ||
421 | ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); | ||
422 | if (ret == 0) | ||
423 | return ret; | ||
424 | |||
425 | pnx4008_stop_hc(); | ||
426 | out4: | ||
427 | pnx4008_unset_usb_bits(); | ||
428 | usb_put_hcd(hcd); | ||
429 | out3: | ||
430 | clk_disable(usb_clk); | ||
431 | out2: | ||
432 | clk_put(usb_clk); | ||
433 | out1: | ||
434 | i2c_del_driver(&isp1301_driver); | ||
435 | out: | ||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | static int usb_hcd_pnx4008_remove(struct platform_device *pdev) | ||
440 | { | ||
441 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
442 | |||
443 | usb_remove_hcd(hcd); | ||
444 | pnx4008_stop_hc(); | ||
445 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
446 | usb_put_hcd(hcd); | ||
447 | pnx4008_unset_usb_bits(); | ||
448 | clk_disable(usb_clk); | ||
449 | clk_put(usb_clk); | ||
450 | i2c_del_driver(&isp1301_driver); | ||
451 | |||
452 | platform_set_drvdata(pdev, NULL); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static struct platform_driver usb_hcd_pnx4008_driver = { | ||
458 | .driver = { | ||
459 | .name = "usb-ohci", | ||
460 | }, | ||
461 | .probe = usb_hcd_pnx4008_probe, | ||
462 | .remove = usb_hcd_pnx4008_remove, | ||
463 | }; | ||
464 | |||
465 | static int __init usb_hcd_pnx4008_init(void) | ||
466 | { | ||
467 | return platform_driver_register(&usb_hcd_pnx4008_driver); | ||
468 | } | ||
469 | |||
470 | static void __exit usb_hcd_pnx4008_cleanup(void) | ||
471 | { | ||
472 | return platform_driver_unregister(&usb_hcd_pnx4008_driver); | ||
473 | } | ||
474 | |||
475 | module_init(usb_hcd_pnx4008_init); | ||
476 | module_exit(usb_hcd_pnx4008_cleanup); | ||
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 9fe56ff1615d..d9d1ae236bd5 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
@@ -148,6 +148,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { | |||
148 | */ | 148 | */ |
149 | .start = ohci_ppc_soc_start, | 149 | .start = ohci_ppc_soc_start, |
150 | .stop = ohci_stop, | 150 | .stop = ohci_stop, |
151 | .shutdown = ohci_shutdown, | ||
151 | 152 | ||
152 | /* | 153 | /* |
153 | * managing i/o requests and associated device resources | 154 | * managing i/o requests and associated device resources |
@@ -166,6 +167,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { | |||
166 | */ | 167 | */ |
167 | .hub_status_data = ohci_hub_status_data, | 168 | .hub_status_data = ohci_hub_status_data, |
168 | .hub_control = ohci_hub_control, | 169 | .hub_control = ohci_hub_control, |
170 | .hub_irq_enable = ohci_rhsc_enable, | ||
169 | #ifdef CONFIG_PM | 171 | #ifdef CONFIG_PM |
170 | .bus_suspend = ohci_bus_suspend, | 172 | .bus_suspend = ohci_bus_suspend, |
171 | .bus_resume = ohci_bus_resume, | 173 | .bus_resume = ohci_bus_resume, |
@@ -195,6 +197,7 @@ static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) | |||
195 | static struct platform_driver ohci_hcd_ppc_soc_driver = { | 197 | static struct platform_driver ohci_hcd_ppc_soc_driver = { |
196 | .probe = ohci_hcd_ppc_soc_drv_probe, | 198 | .probe = ohci_hcd_ppc_soc_drv_probe, |
197 | .remove = ohci_hcd_ppc_soc_drv_remove, | 199 | .remove = ohci_hcd_ppc_soc_drv_remove, |
200 | .shutdown = usb_hcd_platform_shutdown, | ||
198 | #ifdef CONFIG_PM | 201 | #ifdef CONFIG_PM |
199 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ | 202 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ |
200 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ | 203 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 6f559e102789..e176b04d7aeb 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
@@ -270,6 +270,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { | |||
270 | */ | 270 | */ |
271 | .start = ohci_pxa27x_start, | 271 | .start = ohci_pxa27x_start, |
272 | .stop = ohci_stop, | 272 | .stop = ohci_stop, |
273 | .shutdown = ohci_shutdown, | ||
273 | 274 | ||
274 | /* | 275 | /* |
275 | * managing i/o requests and associated device resources | 276 | * managing i/o requests and associated device resources |
@@ -288,6 +289,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { | |||
288 | */ | 289 | */ |
289 | .hub_status_data = ohci_hub_status_data, | 290 | .hub_status_data = ohci_hub_status_data, |
290 | .hub_control = ohci_hub_control, | 291 | .hub_control = ohci_hub_control, |
292 | .hub_irq_enable = ohci_rhsc_enable, | ||
291 | #ifdef CONFIG_PM | 293 | #ifdef CONFIG_PM |
292 | .bus_suspend = ohci_bus_suspend, | 294 | .bus_suspend = ohci_bus_suspend, |
293 | .bus_resume = ohci_bus_resume, | 295 | .bus_resume = ohci_bus_resume, |
@@ -357,6 +359,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev) | |||
357 | static struct platform_driver ohci_hcd_pxa27x_driver = { | 359 | static struct platform_driver ohci_hcd_pxa27x_driver = { |
358 | .probe = ohci_hcd_pxa27x_drv_probe, | 360 | .probe = ohci_hcd_pxa27x_drv_probe, |
359 | .remove = ohci_hcd_pxa27x_drv_remove, | 361 | .remove = ohci_hcd_pxa27x_drv_remove, |
362 | .shutdown = usb_hcd_platform_shutdown, | ||
360 | #ifdef CONFIG_PM | 363 | #ifdef CONFIG_PM |
361 | .suspend = ohci_hcd_pxa27x_drv_suspend, | 364 | .suspend = ohci_hcd_pxa27x_drv_suspend, |
362 | .resume = ohci_hcd_pxa27x_drv_resume, | 365 | .resume = ohci_hcd_pxa27x_drv_resume, |
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index d2fc6969a9f7..59e436424d41 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c | |||
@@ -370,7 +370,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, | |||
370 | goto err_mem; | 370 | goto err_mem; |
371 | } | 371 | } |
372 | 372 | ||
373 | usb_clk = clk_get(&dev->dev, "upll"); | 373 | usb_clk = clk_get(&dev->dev, "usb-bus-host"); |
374 | if (IS_ERR(usb_clk)) { | 374 | if (IS_ERR(usb_clk)) { |
375 | dev_err(&dev->dev, "cannot get usb-host clock\n"); | 375 | dev_err(&dev->dev, "cannot get usb-host clock\n"); |
376 | retval = -ENOENT; | 376 | retval = -ENOENT; |
@@ -447,6 +447,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { | |||
447 | */ | 447 | */ |
448 | .start = ohci_s3c2410_start, | 448 | .start = ohci_s3c2410_start, |
449 | .stop = ohci_stop, | 449 | .stop = ohci_stop, |
450 | .shutdown = ohci_shutdown, | ||
450 | 451 | ||
451 | /* | 452 | /* |
452 | * managing i/o requests and associated device resources | 453 | * managing i/o requests and associated device resources |
@@ -465,6 +466,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { | |||
465 | */ | 466 | */ |
466 | .hub_status_data = ohci_s3c2410_hub_status_data, | 467 | .hub_status_data = ohci_s3c2410_hub_status_data, |
467 | .hub_control = ohci_s3c2410_hub_control, | 468 | .hub_control = ohci_s3c2410_hub_control, |
469 | .hub_irq_enable = ohci_rhsc_enable, | ||
468 | #ifdef CONFIG_PM | 470 | #ifdef CONFIG_PM |
469 | .bus_suspend = ohci_bus_suspend, | 471 | .bus_suspend = ohci_bus_suspend, |
470 | .bus_resume = ohci_bus_resume, | 472 | .bus_resume = ohci_bus_resume, |
@@ -490,6 +492,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) | |||
490 | static struct platform_driver ohci_hcd_s3c2410_driver = { | 492 | static struct platform_driver ohci_hcd_s3c2410_driver = { |
491 | .probe = ohci_hcd_s3c2410_drv_probe, | 493 | .probe = ohci_hcd_s3c2410_drv_probe, |
492 | .remove = ohci_hcd_s3c2410_drv_remove, | 494 | .remove = ohci_hcd_s3c2410_drv_remove, |
495 | .shutdown = usb_hcd_platform_shutdown, | ||
493 | /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ | 496 | /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ |
494 | /*.resume = ohci_hcd_s3c2410_drv_resume, */ | 497 | /*.resume = ohci_hcd_s3c2410_drv_resume, */ |
495 | .driver = { | 498 | .driver = { |
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index ce3de106cadc..71371de32ada 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c | |||
@@ -212,10 +212,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = { | |||
212 | * basic lifecycle operations | 212 | * basic lifecycle operations |
213 | */ | 213 | */ |
214 | .start = ohci_sa1111_start, | 214 | .start = ohci_sa1111_start, |
215 | #ifdef CONFIG_PM | ||
216 | /* suspend: ohci_sa1111_suspend, -- tbd */ | ||
217 | /* resume: ohci_sa1111_resume, -- tbd */ | ||
218 | #endif | ||
219 | .stop = ohci_stop, | 215 | .stop = ohci_stop, |
220 | 216 | ||
221 | /* | 217 | /* |
@@ -235,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = { | |||
235 | */ | 231 | */ |
236 | .hub_status_data = ohci_hub_status_data, | 232 | .hub_status_data = ohci_hub_status_data, |
237 | .hub_control = ohci_hub_control, | 233 | .hub_control = ohci_hub_control, |
234 | .hub_irq_enable = ohci_rhsc_enable, | ||
238 | #ifdef CONFIG_PM | 235 | #ifdef CONFIG_PM |
239 | .bus_suspend = ohci_bus_suspend, | 236 | .bus_suspend = ohci_bus_suspend, |
240 | .bus_resume = ohci_bus_resume, | 237 | .bus_resume = ohci_bus_resume, |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index caacf14371f5..93fdc3c35341 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -159,7 +159,7 @@ static const int cc_to_error [16] = { | |||
159 | /* Bit Stuff */ -EPROTO, | 159 | /* Bit Stuff */ -EPROTO, |
160 | /* Data Togg */ -EILSEQ, | 160 | /* Data Togg */ -EILSEQ, |
161 | /* Stall */ -EPIPE, | 161 | /* Stall */ -EPIPE, |
162 | /* DevNotResp */ -ETIMEDOUT, | 162 | /* DevNotResp */ -ETIME, |
163 | /* PIDCheck */ -EPROTO, | 163 | /* PIDCheck */ -EPROTO, |
164 | /* UnExpPID */ -EPROTO, | 164 | /* UnExpPID */ -EPROTO, |
165 | /* DataOver */ -EOVERFLOW, | 165 | /* DataOver */ -EOVERFLOW, |
@@ -389,8 +389,6 @@ struct ohci_hcd { | |||
389 | unsigned long next_statechange; /* suspend/resume */ | 389 | unsigned long next_statechange; /* suspend/resume */ |
390 | u32 fminterval; /* saved register */ | 390 | u32 fminterval; /* saved register */ |
391 | 391 | ||
392 | struct notifier_block reboot_notifier; | ||
393 | |||
394 | unsigned long flags; /* for HC bugs */ | 392 | unsigned long flags; /* for HC bugs */ |
395 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ | 393 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ |
396 | #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ | 394 | #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index fa34092bbcde..3a586aab3939 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -597,7 +597,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs) | |||
597 | /* error? retry, until "3 strikes" */ | 597 | /* error? retry, until "3 strikes" */ |
598 | } else if (++ep->error_count >= 3) { | 598 | } else if (++ep->error_count >= 3) { |
599 | if (status & SL11H_STATMASK_TMOUT) | 599 | if (status & SL11H_STATMASK_TMOUT) |
600 | urbstat = -ETIMEDOUT; | 600 | urbstat = -ETIME; |
601 | else if (status & SL11H_STATMASK_OVF) | 601 | else if (status & SL11H_STATMASK_OVF) |
602 | urbstat = -EOVERFLOW; | 602 | urbstat = -EOVERFLOW; |
603 | else | 603 | else |
@@ -1517,7 +1517,7 @@ static int proc_sl811h_open(struct inode *inode, struct file *file) | |||
1517 | return single_open(file, proc_sl811h_show, PDE(inode)->data); | 1517 | return single_open(file, proc_sl811h_show, PDE(inode)->data); |
1518 | } | 1518 | } |
1519 | 1519 | ||
1520 | static struct file_operations proc_ops = { | 1520 | static const struct file_operations proc_ops = { |
1521 | .open = proc_sl811h_open, | 1521 | .open = proc_sl811h_open, |
1522 | .read = seq_read, | 1522 | .read = seq_read, |
1523 | .llseek = seq_lseek, | 1523 | .llseek = seq_lseek, |
@@ -1783,10 +1783,15 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state) | |||
1783 | struct sl811 *sl811 = hcd_to_sl811(hcd); | 1783 | struct sl811 *sl811 = hcd_to_sl811(hcd); |
1784 | int retval = 0; | 1784 | int retval = 0; |
1785 | 1785 | ||
1786 | if (state.event == PM_EVENT_FREEZE) | 1786 | switch (state.event) { |
1787 | case PM_EVENT_FREEZE: | ||
1787 | retval = sl811h_bus_suspend(hcd); | 1788 | retval = sl811h_bus_suspend(hcd); |
1788 | else if (state.event == PM_EVENT_SUSPEND) | 1789 | break; |
1790 | case PM_EVENT_SUSPEND: | ||
1791 | case PM_EVENT_PRETHAW: /* explicitly discard hw state */ | ||
1789 | port_power(sl811, 0); | 1792 | port_power(sl811, 0); |
1793 | break; | ||
1794 | } | ||
1790 | if (retval == 0) | 1795 | if (retval == 0) |
1791 | dev->dev.power.power_state = state; | 1796 | dev->dev.power.power_state = state; |
1792 | return retval; | 1797 | return retval; |
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c new file mode 100644 index 000000000000..cb2e2a604d1b --- /dev/null +++ b/drivers/usb/host/u132-hcd.c | |||
@@ -0,0 +1,3295 @@ | |||
1 | /* | ||
2 | * Host Controller Driver for the Elan Digital Systems U132 adapter | ||
3 | * | ||
4 | * Copyright(C) 2006 Elan Digital Systems Limited | ||
5 | * http://www.elandigitalsystems.com | ||
6 | * | ||
7 | * Author and Maintainer - Tony Olech - Elan Digital Systems | ||
8 | * tony.olech@elandigitalsystems.com | ||
9 | * | ||
10 | * This program is free software;you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation, version 2. | ||
13 | * | ||
14 | * | ||
15 | * This driver was written by Tony Olech(tony.olech@elandigitalsystems.com) | ||
16 | * based on various USB host drivers in the 2.6.15 linux kernel | ||
17 | * with constant reference to the 3rd Edition of Linux Device Drivers | ||
18 | * published by O'Reilly | ||
19 | * | ||
20 | * The U132 adapter is a USB to CardBus adapter specifically designed | ||
21 | * for PC cards that contain an OHCI host controller. Typical PC cards | ||
22 | * are the Orange Mobile 3G Option GlobeTrotter Fusion card. | ||
23 | * | ||
24 | * The U132 adapter will *NOT *work with PC cards that do not contain | ||
25 | * an OHCI controller. A simple way to test whether a PC card has an | ||
26 | * OHCI controller as an interface is to insert the PC card directly | ||
27 | * into a laptop(or desktop) with a CardBus slot and if "lspci" shows | ||
28 | * a new USB controller and "lsusb -v" shows a new OHCI Host Controller | ||
29 | * then there is a good chance that the U132 adapter will support the | ||
30 | * PC card.(you also need the specific client driver for the PC card) | ||
31 | * | ||
32 | * Please inform the Author and Maintainer about any PC cards that | ||
33 | * contain OHCI Host Controller and work when directly connected to | ||
34 | * an embedded CardBus slot but do not work when they are connected | ||
35 | * via an ELAN U132 adapter. | ||
36 | * | ||
37 | */ | ||
38 | #include <linux/config.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/moduleparam.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <linux/ioport.h> | ||
44 | #include <linux/sched.h> | ||
45 | #include <linux/slab.h> | ||
46 | #include <linux/smp_lock.h> | ||
47 | #include <linux/errno.h> | ||
48 | #include <linux/init.h> | ||
49 | #include <linux/timer.h> | ||
50 | #include <linux/list.h> | ||
51 | #include <linux/interrupt.h> | ||
52 | #include <linux/usb.h> | ||
53 | #include <linux/workqueue.h> | ||
54 | #include <linux/platform_device.h> | ||
55 | #include <linux/pci_ids.h> | ||
56 | #include <asm/io.h> | ||
57 | #include <asm/irq.h> | ||
58 | #include <asm/system.h> | ||
59 | #include <asm/byteorder.h> | ||
60 | #include "../core/hcd.h" | ||
61 | #include "ohci.h" | ||
62 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR | ||
63 | #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ | ||
64 | OHCI_INTR_WDH) | ||
65 | MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited"); | ||
66 | MODULE_DESCRIPTION("U132 USB Host Controller Driver"); | ||
67 | MODULE_LICENSE("GPL"); | ||
68 | #define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444) | ||
69 | INT_MODULE_PARM(testing, 0); | ||
70 | /* Some boards misreport power switching/overcurrent*/ | ||
71 | static int distrust_firmware = 1; | ||
72 | module_param(distrust_firmware, bool, 0); | ||
73 | MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren" | ||
74 | "t setup"); | ||
75 | DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait); | ||
76 | /* | ||
77 | * u132_module_lock exists to protect access to global variables | ||
78 | * | ||
79 | */ | ||
80 | static struct semaphore u132_module_lock; | ||
81 | static int u132_exiting = 0; | ||
82 | static int u132_instances = 0; | ||
83 | static struct list_head u132_static_list; | ||
84 | /* | ||
85 | * end of the global variables protected by u132_module_lock | ||
86 | */ | ||
87 | static struct workqueue_struct *workqueue; | ||
88 | #define MAX_U132_PORTS 7 | ||
89 | #define MAX_U132_ADDRS 128 | ||
90 | #define MAX_U132_UDEVS 4 | ||
91 | #define MAX_U132_ENDPS 100 | ||
92 | #define MAX_U132_RINGS 4 | ||
93 | static const char *cc_to_text[16] = { | ||
94 | "No Error ", | ||
95 | "CRC Error ", | ||
96 | "Bit Stuff ", | ||
97 | "Data Togg ", | ||
98 | "Stall ", | ||
99 | "DevNotResp ", | ||
100 | "PIDCheck ", | ||
101 | "UnExpPID ", | ||
102 | "DataOver ", | ||
103 | "DataUnder ", | ||
104 | "(for hw) ", | ||
105 | "(for hw) ", | ||
106 | "BufferOver ", | ||
107 | "BuffUnder ", | ||
108 | "(for HCD) ", | ||
109 | "(for HCD) " | ||
110 | }; | ||
111 | struct u132_port { | ||
112 | struct u132 *u132; | ||
113 | int reset; | ||
114 | int enable; | ||
115 | int power; | ||
116 | int Status; | ||
117 | }; | ||
118 | struct u132_addr { | ||
119 | u8 address; | ||
120 | }; | ||
121 | struct u132_udev { | ||
122 | struct kref kref; | ||
123 | struct usb_device *usb_device; | ||
124 | u8 enumeration; | ||
125 | u8 udev_number; | ||
126 | u8 usb_addr; | ||
127 | u8 portnumber; | ||
128 | u8 endp_number_in[16]; | ||
129 | u8 endp_number_out[16]; | ||
130 | }; | ||
131 | #define ENDP_QUEUE_SHIFT 3 | ||
132 | #define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT) | ||
133 | #define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1) | ||
134 | struct u132_urbq { | ||
135 | struct list_head urb_more; | ||
136 | struct urb *urb; | ||
137 | }; | ||
138 | struct u132_spin { | ||
139 | spinlock_t slock; | ||
140 | }; | ||
141 | struct u132_endp { | ||
142 | struct kref kref; | ||
143 | u8 udev_number; | ||
144 | u8 endp_number; | ||
145 | u8 usb_addr; | ||
146 | u8 usb_endp; | ||
147 | struct u132 *u132; | ||
148 | struct list_head endp_ring; | ||
149 | struct u132_ring *ring; | ||
150 | unsigned toggle_bits:2; | ||
151 | unsigned active:1; | ||
152 | unsigned delayed:1; | ||
153 | unsigned input:1; | ||
154 | unsigned output:1; | ||
155 | unsigned pipetype:2; | ||
156 | unsigned dequeueing:1; | ||
157 | unsigned edset_flush:1; | ||
158 | unsigned spare_bits:14; | ||
159 | unsigned long jiffies; | ||
160 | struct usb_host_endpoint *hep; | ||
161 | struct u132_spin queue_lock; | ||
162 | u16 queue_size; | ||
163 | u16 queue_last; | ||
164 | u16 queue_next; | ||
165 | struct urb *urb_list[ENDP_QUEUE_SIZE]; | ||
166 | struct list_head urb_more; | ||
167 | struct work_struct scheduler; | ||
168 | }; | ||
169 | struct u132_ring { | ||
170 | unsigned in_use:1; | ||
171 | unsigned length:7; | ||
172 | u8 number; | ||
173 | struct u132 *u132; | ||
174 | struct u132_endp *curr_endp; | ||
175 | struct work_struct scheduler; | ||
176 | }; | ||
177 | #define OHCI_QUIRK_AMD756 0x01 | ||
178 | #define OHCI_QUIRK_SUPERIO 0x02 | ||
179 | #define OHCI_QUIRK_INITRESET 0x04 | ||
180 | #define OHCI_BIG_ENDIAN 0x08 | ||
181 | #define OHCI_QUIRK_ZFMICRO 0x10 | ||
182 | struct u132 { | ||
183 | struct kref kref; | ||
184 | struct list_head u132_list; | ||
185 | struct semaphore sw_lock; | ||
186 | struct semaphore scheduler_lock; | ||
187 | struct u132_platform_data *board; | ||
188 | struct platform_device *platform_dev; | ||
189 | struct u132_ring ring[MAX_U132_RINGS]; | ||
190 | int sequence_num; | ||
191 | int going; | ||
192 | int power; | ||
193 | int reset; | ||
194 | int num_ports; | ||
195 | u32 hc_control; | ||
196 | u32 hc_fminterval; | ||
197 | u32 hc_roothub_status; | ||
198 | u32 hc_roothub_a; | ||
199 | u32 hc_roothub_portstatus[MAX_ROOT_PORTS]; | ||
200 | int flags; | ||
201 | unsigned long next_statechange; | ||
202 | struct work_struct monitor; | ||
203 | int num_endpoints; | ||
204 | struct u132_addr addr[MAX_U132_ADDRS]; | ||
205 | struct u132_udev udev[MAX_U132_UDEVS]; | ||
206 | struct u132_port port[MAX_U132_PORTS]; | ||
207 | struct u132_endp *endp[MAX_U132_ENDPS]; | ||
208 | }; | ||
209 | int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data); | ||
210 | int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs, | ||
211 | u8 width, u32 *data); | ||
212 | int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs, | ||
213 | u8 width, u32 data); | ||
214 | /* | ||
215 | * these can not be inlines because we need the structure offset!! | ||
216 | * Does anyone have a better way????? | ||
217 | */ | ||
218 | #define u132_read_pcimem(u132, member, data) \ | ||
219 | usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ | ||
220 | ohci_regs, member), 0, data); | ||
221 | #define u132_write_pcimem(u132, member, data) \ | ||
222 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | ||
223 | ohci_regs, member), 0, data); | ||
224 | #define u132_write_pcimem_byte(u132, member, data) \ | ||
225 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | ||
226 | ohci_regs, member), 0x0e, data); | ||
227 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) | ||
228 | { | ||
229 | u8 udev_number = udev->udev_number; | ||
230 | return container_of(udev, struct u132, udev[udev_number]); | ||
231 | } | ||
232 | |||
233 | static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd) | ||
234 | { | ||
235 | return (struct u132 *)(hcd->hcd_priv); | ||
236 | } | ||
237 | |||
238 | static inline struct usb_hcd *u132_to_hcd(struct u132 *u132) | ||
239 | { | ||
240 | return container_of((void *)u132, struct usb_hcd, hcd_priv); | ||
241 | } | ||
242 | |||
243 | static inline void u132_disable(struct u132 *u132) | ||
244 | { | ||
245 | u132_to_hcd(u132)->state = HC_STATE_HALT; | ||
246 | } | ||
247 | |||
248 | |||
249 | #define kref_to_u132(d) container_of(d, struct u132, kref) | ||
250 | #define kref_to_u132_endp(d) container_of(d, struct u132_endp, kref) | ||
251 | #define kref_to_u132_udev(d) container_of(d, struct u132_udev, kref) | ||
252 | #include "../misc/usb_u132.h" | ||
253 | static const char hcd_name[] = "u132_hcd"; | ||
254 | #define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \ | ||
255 | USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \ | ||
256 | USB_PORT_STAT_C_RESET) << 16) | ||
257 | static void u132_hcd_delete(struct kref *kref) | ||
258 | { | ||
259 | struct u132 *u132 = kref_to_u132(kref); | ||
260 | struct platform_device *pdev = u132->platform_dev; | ||
261 | struct usb_hcd *hcd = u132_to_hcd(u132); | ||
262 | u132->going += 1; | ||
263 | down(&u132_module_lock); | ||
264 | list_del_init(&u132->u132_list); | ||
265 | u132_instances -= 1; | ||
266 | up(&u132_module_lock); | ||
267 | dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13" | ||
268 | "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev); | ||
269 | usb_put_hcd(hcd); | ||
270 | } | ||
271 | |||
272 | static inline void u132_u132_put_kref(struct u132 *u132) | ||
273 | { | ||
274 | kref_put(&u132->kref, u132_hcd_delete); | ||
275 | } | ||
276 | |||
277 | static inline void u132_u132_init_kref(struct u132 *u132) | ||
278 | { | ||
279 | kref_init(&u132->kref); | ||
280 | } | ||
281 | |||
282 | static void u132_udev_delete(struct kref *kref) | ||
283 | { | ||
284 | struct u132_udev *udev = kref_to_u132_udev(kref); | ||
285 | udev->udev_number = 0; | ||
286 | udev->usb_device = NULL; | ||
287 | udev->usb_addr = 0; | ||
288 | udev->enumeration = 0; | ||
289 | } | ||
290 | |||
291 | static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev) | ||
292 | { | ||
293 | kref_put(&udev->kref, u132_udev_delete); | ||
294 | } | ||
295 | |||
296 | static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev) | ||
297 | { | ||
298 | kref_get(&udev->kref); | ||
299 | } | ||
300 | |||
301 | static inline void u132_udev_init_kref(struct u132 *u132, | ||
302 | struct u132_udev *udev) | ||
303 | { | ||
304 | kref_init(&udev->kref); | ||
305 | } | ||
306 | |||
307 | static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring) | ||
308 | { | ||
309 | kref_put(&u132->kref, u132_hcd_delete); | ||
310 | } | ||
311 | |||
312 | static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring, | ||
313 | unsigned int delta) | ||
314 | { | ||
315 | if (delta > 0) { | ||
316 | if (queue_delayed_work(workqueue, &ring->scheduler, delta)) | ||
317 | return; | ||
318 | } else if (queue_work(workqueue, &ring->scheduler)) | ||
319 | return; | ||
320 | kref_put(&u132->kref, u132_hcd_delete); | ||
321 | return; | ||
322 | } | ||
323 | |||
324 | static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring, | ||
325 | unsigned int delta) | ||
326 | { | ||
327 | kref_get(&u132->kref); | ||
328 | u132_ring_requeue_work(u132, ring, delta); | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring) | ||
333 | { | ||
334 | if (cancel_delayed_work(&ring->scheduler)) { | ||
335 | kref_put(&u132->kref, u132_hcd_delete); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static void u132_endp_delete(struct kref *kref) | ||
340 | { | ||
341 | struct u132_endp *endp = kref_to_u132_endp(kref); | ||
342 | struct u132 *u132 = endp->u132; | ||
343 | u8 usb_addr = endp->usb_addr; | ||
344 | u8 usb_endp = endp->usb_endp; | ||
345 | u8 address = u132->addr[usb_addr].address; | ||
346 | struct u132_udev *udev = &u132->udev[address]; | ||
347 | u8 endp_number = endp->endp_number; | ||
348 | struct usb_host_endpoint *hep = endp->hep; | ||
349 | struct u132_ring *ring = endp->ring; | ||
350 | struct list_head *head = &endp->endp_ring; | ||
351 | ring->length -= 1; | ||
352 | if (endp == ring->curr_endp) { | ||
353 | if (list_empty(head)) { | ||
354 | ring->curr_endp = NULL; | ||
355 | list_del(head); | ||
356 | } else { | ||
357 | struct u132_endp *next_endp = list_entry(head->next, | ||
358 | struct u132_endp, endp_ring); | ||
359 | ring->curr_endp = next_endp; | ||
360 | list_del(head); | ||
361 | }} else | ||
362 | list_del(head); | ||
363 | if (endp->input) { | ||
364 | udev->endp_number_in[usb_endp] = 0; | ||
365 | u132_udev_put_kref(u132, udev); | ||
366 | } | ||
367 | if (endp->output) { | ||
368 | udev->endp_number_out[usb_endp] = 0; | ||
369 | u132_udev_put_kref(u132, udev); | ||
370 | } | ||
371 | u132->endp[endp_number - 1] = NULL; | ||
372 | hep->hcpriv = NULL; | ||
373 | kfree(endp); | ||
374 | u132_u132_put_kref(u132); | ||
375 | } | ||
376 | |||
377 | static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp) | ||
378 | { | ||
379 | kref_put(&endp->kref, u132_endp_delete); | ||
380 | } | ||
381 | |||
382 | static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp) | ||
383 | { | ||
384 | kref_get(&endp->kref); | ||
385 | } | ||
386 | |||
387 | static inline void u132_endp_init_kref(struct u132 *u132, | ||
388 | struct u132_endp *endp) | ||
389 | { | ||
390 | kref_init(&endp->kref); | ||
391 | kref_get(&u132->kref); | ||
392 | } | ||
393 | |||
394 | static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp, | ||
395 | unsigned int delta) | ||
396 | { | ||
397 | if (delta > 0) { | ||
398 | if (queue_delayed_work(workqueue, &endp->scheduler, delta)) | ||
399 | kref_get(&endp->kref); | ||
400 | } else if (queue_work(workqueue, &endp->scheduler)) | ||
401 | kref_get(&endp->kref); | ||
402 | return; | ||
403 | } | ||
404 | |||
405 | static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp) | ||
406 | { | ||
407 | if (cancel_delayed_work(&endp->scheduler)) | ||
408 | kref_put(&endp->kref, u132_endp_delete); | ||
409 | } | ||
410 | |||
411 | static inline void u132_monitor_put_kref(struct u132 *u132) | ||
412 | { | ||
413 | kref_put(&u132->kref, u132_hcd_delete); | ||
414 | } | ||
415 | |||
416 | static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta) | ||
417 | { | ||
418 | if (delta > 0) { | ||
419 | if (queue_delayed_work(workqueue, &u132->monitor, delta)) { | ||
420 | kref_get(&u132->kref); | ||
421 | } | ||
422 | } else if (queue_work(workqueue, &u132->monitor)) | ||
423 | kref_get(&u132->kref); | ||
424 | return; | ||
425 | } | ||
426 | |||
427 | static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta) | ||
428 | { | ||
429 | if (delta > 0) { | ||
430 | if (queue_delayed_work(workqueue, &u132->monitor, delta)) | ||
431 | return; | ||
432 | } else if (queue_work(workqueue, &u132->monitor)) | ||
433 | return; | ||
434 | kref_put(&u132->kref, u132_hcd_delete); | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | static void u132_monitor_cancel_work(struct u132 *u132) | ||
439 | { | ||
440 | if (cancel_delayed_work(&u132->monitor)) | ||
441 | kref_put(&u132->kref, u132_hcd_delete); | ||
442 | } | ||
443 | |||
444 | static int read_roothub_info(struct u132 *u132) | ||
445 | { | ||
446 | u32 revision; | ||
447 | int retval; | ||
448 | retval = u132_read_pcimem(u132, revision, &revision); | ||
449 | if (retval) { | ||
450 | dev_err(&u132->platform_dev->dev, "error %d accessing device co" | ||
451 | "ntrol\n", retval); | ||
452 | return retval; | ||
453 | } else if ((revision & 0xFF) == 0x10) { | ||
454 | } else if ((revision & 0xFF) == 0x11) { | ||
455 | } else { | ||
456 | dev_err(&u132->platform_dev->dev, "device revision is not valid" | ||
457 | " %08X\n", revision); | ||
458 | return -ENODEV; | ||
459 | } | ||
460 | retval = u132_read_pcimem(u132, control, &u132->hc_control); | ||
461 | if (retval) { | ||
462 | dev_err(&u132->platform_dev->dev, "error %d accessing device co" | ||
463 | "ntrol\n", retval); | ||
464 | return retval; | ||
465 | } | ||
466 | retval = u132_read_pcimem(u132, roothub.status, | ||
467 | &u132->hc_roothub_status); | ||
468 | if (retval) { | ||
469 | dev_err(&u132->platform_dev->dev, "error %d accessing device re" | ||
470 | "g roothub.status\n", retval); | ||
471 | return retval; | ||
472 | } | ||
473 | retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a); | ||
474 | if (retval) { | ||
475 | dev_err(&u132->platform_dev->dev, "error %d accessing device re" | ||
476 | "g roothub.a\n", retval); | ||
477 | return retval; | ||
478 | } | ||
479 | { | ||
480 | int I = u132->num_ports; | ||
481 | int i = 0; | ||
482 | while (I-- > 0) { | ||
483 | retval = u132_read_pcimem(u132, roothub.portstatus[i], | ||
484 | &u132->hc_roothub_portstatus[i]); | ||
485 | if (retval) { | ||
486 | dev_err(&u132->platform_dev->dev, "error %d acc" | ||
487 | "essing device roothub.portstatus[%d]\n" | ||
488 | , retval, i); | ||
489 | return retval; | ||
490 | } else | ||
491 | i += 1; | ||
492 | } | ||
493 | } | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static void u132_hcd_monitor_work(void *data) | ||
498 | { | ||
499 | struct u132 *u132 = data; | ||
500 | if (u132->going > 1) { | ||
501 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
502 | , u132->going); | ||
503 | u132_monitor_put_kref(u132); | ||
504 | return; | ||
505 | } else if (u132->going > 0) { | ||
506 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
507 | u132_monitor_put_kref(u132); | ||
508 | return; | ||
509 | } else { | ||
510 | int retval; | ||
511 | down(&u132->sw_lock); | ||
512 | retval = read_roothub_info(u132); | ||
513 | if (retval) { | ||
514 | struct usb_hcd *hcd = u132_to_hcd(u132); | ||
515 | u132_disable(u132); | ||
516 | u132->going = 1; | ||
517 | up(&u132->sw_lock); | ||
518 | usb_hc_died(hcd); | ||
519 | ftdi_elan_gone_away(u132->platform_dev); | ||
520 | u132_monitor_put_kref(u132); | ||
521 | return; | ||
522 | } else { | ||
523 | u132_monitor_requeue_work(u132, 500); | ||
524 | up(&u132->sw_lock); | ||
525 | return; | ||
526 | } | ||
527 | } | ||
528 | } | ||
529 | |||
530 | static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp, | ||
531 | struct urb *urb, int status) | ||
532 | { | ||
533 | struct u132_ring *ring; | ||
534 | unsigned long irqs; | ||
535 | struct usb_hcd *hcd = u132_to_hcd(u132); | ||
536 | urb->error_count = 0; | ||
537 | urb->status = status; | ||
538 | urb->hcpriv = NULL; | ||
539 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
540 | endp->queue_next += 1; | ||
541 | if (ENDP_QUEUE_SIZE > --endp->queue_size) { | ||
542 | endp->active = 0; | ||
543 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
544 | } else { | ||
545 | struct list_head *next = endp->urb_more.next; | ||
546 | struct u132_urbq *urbq = list_entry(next, struct u132_urbq, | ||
547 | urb_more); | ||
548 | list_del(next); | ||
549 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = | ||
550 | urbq->urb; | ||
551 | endp->active = 0; | ||
552 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
553 | kfree(urbq); | ||
554 | } down(&u132->scheduler_lock); | ||
555 | ring = endp->ring; | ||
556 | ring->in_use = 0; | ||
557 | u132_ring_cancel_work(u132, ring); | ||
558 | u132_ring_queue_work(u132, ring, 0); | ||
559 | up(&u132->scheduler_lock); | ||
560 | u132_endp_put_kref(u132, endp); | ||
561 | usb_hcd_giveback_urb(hcd, urb, NULL); | ||
562 | return; | ||
563 | } | ||
564 | |||
565 | static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp, | ||
566 | struct urb *urb, int status) | ||
567 | { | ||
568 | u132_endp_put_kref(u132, endp); | ||
569 | } | ||
570 | |||
571 | static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp, | ||
572 | struct urb *urb, int status) | ||
573 | { | ||
574 | unsigned long irqs; | ||
575 | struct usb_hcd *hcd = u132_to_hcd(u132); | ||
576 | urb->error_count = 0; | ||
577 | urb->status = status; | ||
578 | urb->hcpriv = NULL; | ||
579 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
580 | endp->queue_next += 1; | ||
581 | if (ENDP_QUEUE_SIZE > --endp->queue_size) { | ||
582 | endp->active = 0; | ||
583 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
584 | } else { | ||
585 | struct list_head *next = endp->urb_more.next; | ||
586 | struct u132_urbq *urbq = list_entry(next, struct u132_urbq, | ||
587 | urb_more); | ||
588 | list_del(next); | ||
589 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = | ||
590 | urbq->urb; | ||
591 | endp->active = 0; | ||
592 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
593 | kfree(urbq); | ||
594 | } usb_hcd_giveback_urb(hcd, urb, NULL); | ||
595 | return; | ||
596 | } | ||
597 | |||
598 | static inline int edset_input(struct u132 *u132, struct u132_ring *ring, | ||
599 | struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | ||
600 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
601 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
602 | int halted, int skipped, int actual, int non_null)) | ||
603 | { | ||
604 | return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp, | ||
605 | urb, address, endp->usb_endp, toggle_bits, callback); | ||
606 | } | ||
607 | |||
608 | static inline int edset_setup(struct u132 *u132, struct u132_ring *ring, | ||
609 | struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | ||
610 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
611 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
612 | int halted, int skipped, int actual, int non_null)) | ||
613 | { | ||
614 | return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp, | ||
615 | urb, address, endp->usb_endp, toggle_bits, callback); | ||
616 | } | ||
617 | |||
618 | static inline int edset_single(struct u132 *u132, struct u132_ring *ring, | ||
619 | struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | ||
620 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
621 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
622 | int halted, int skipped, int actual, int non_null)) | ||
623 | { | ||
624 | return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number, | ||
625 | endp, urb, address, endp->usb_endp, toggle_bits, callback); | ||
626 | } | ||
627 | |||
628 | static inline int edset_output(struct u132 *u132, struct u132_ring *ring, | ||
629 | struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits, | ||
630 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
631 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
632 | int halted, int skipped, int actual, int non_null)) | ||
633 | { | ||
634 | return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number, | ||
635 | endp, urb, address, endp->usb_endp, toggle_bits, callback); | ||
636 | } | ||
637 | |||
638 | |||
639 | /* | ||
640 | * must not LOCK sw_lock | ||
641 | * | ||
642 | */ | ||
643 | static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf, | ||
644 | int len, int toggle_bits, int error_count, int condition_code, | ||
645 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
646 | { | ||
647 | struct u132_endp *endp = data; | ||
648 | struct u132 *u132 = endp->u132; | ||
649 | u8 address = u132->addr[endp->usb_addr].address; | ||
650 | struct u132_udev *udev = &u132->udev[address]; | ||
651 | down(&u132->scheduler_lock); | ||
652 | if (u132->going > 1) { | ||
653 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
654 | , u132->going); | ||
655 | up(&u132->scheduler_lock); | ||
656 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
657 | return; | ||
658 | } else if (endp->dequeueing) { | ||
659 | endp->dequeueing = 0; | ||
660 | up(&u132->scheduler_lock); | ||
661 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
662 | return; | ||
663 | } else if (u132->going > 0) { | ||
664 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
665 | "%p status=%d\n", urb, urb->status); | ||
666 | up(&u132->scheduler_lock); | ||
667 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
668 | return; | ||
669 | } else if (urb->status == -EINPROGRESS) { | ||
670 | struct u132_ring *ring = endp->ring; | ||
671 | u8 *u = urb->transfer_buffer + urb->actual_length; | ||
672 | u8 *b = buf; | ||
673 | int L = len; | ||
674 | while (L-- > 0) { | ||
675 | *u++ = *b++; | ||
676 | } | ||
677 | urb->actual_length += len; | ||
678 | if ((condition_code == TD_CC_NOERROR) && | ||
679 | (urb->transfer_buffer_length > urb->actual_length)) { | ||
680 | endp->toggle_bits = toggle_bits; | ||
681 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, | ||
682 | 1 & toggle_bits); | ||
683 | if (urb->actual_length > 0) { | ||
684 | int retval; | ||
685 | up(&u132->scheduler_lock); | ||
686 | retval = edset_single(u132, ring, endp, urb, | ||
687 | address, endp->toggle_bits, | ||
688 | u132_hcd_interrupt_recv); | ||
689 | if (retval == 0) { | ||
690 | } else | ||
691 | u132_hcd_giveback_urb(u132, endp, urb, | ||
692 | retval); | ||
693 | } else { | ||
694 | ring->in_use = 0; | ||
695 | endp->active = 0; | ||
696 | endp->jiffies = jiffies + | ||
697 | msecs_to_jiffies(urb->interval); | ||
698 | u132_ring_cancel_work(u132, ring); | ||
699 | u132_ring_queue_work(u132, ring, 0); | ||
700 | up(&u132->scheduler_lock); | ||
701 | u132_endp_put_kref(u132, endp); | ||
702 | } | ||
703 | return; | ||
704 | } else if ((condition_code == TD_DATAUNDERRUN) && | ||
705 | ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) { | ||
706 | endp->toggle_bits = toggle_bits; | ||
707 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, | ||
708 | 1 & toggle_bits); | ||
709 | up(&u132->scheduler_lock); | ||
710 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
711 | return; | ||
712 | } else { | ||
713 | if (condition_code == TD_CC_NOERROR) { | ||
714 | endp->toggle_bits = toggle_bits; | ||
715 | usb_settoggle(udev->usb_device, endp->usb_endp, | ||
716 | 0, 1 & toggle_bits); | ||
717 | } else if (condition_code == TD_CC_STALL) { | ||
718 | endp->toggle_bits = 0x2; | ||
719 | usb_settoggle(udev->usb_device, endp->usb_endp, | ||
720 | 0, 0); | ||
721 | } else { | ||
722 | endp->toggle_bits = 0x2; | ||
723 | usb_settoggle(udev->usb_device, endp->usb_endp, | ||
724 | 0, 0); | ||
725 | dev_err(&u132->platform_dev->dev, "urb=%p givin" | ||
726 | "g back INTERRUPT %s\n", urb, | ||
727 | cc_to_text[condition_code]); | ||
728 | } | ||
729 | up(&u132->scheduler_lock); | ||
730 | u132_hcd_giveback_urb(u132, endp, urb, | ||
731 | cc_to_error[condition_code]); | ||
732 | return; | ||
733 | } | ||
734 | } else { | ||
735 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
736 | "s=%d\n", urb, urb->status); | ||
737 | up(&u132->scheduler_lock); | ||
738 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
739 | return; | ||
740 | } | ||
741 | } | ||
742 | |||
743 | static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf, | ||
744 | int len, int toggle_bits, int error_count, int condition_code, | ||
745 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
746 | { | ||
747 | struct u132_endp *endp = data; | ||
748 | struct u132 *u132 = endp->u132; | ||
749 | u8 address = u132->addr[endp->usb_addr].address; | ||
750 | down(&u132->scheduler_lock); | ||
751 | if (u132->going > 1) { | ||
752 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
753 | , u132->going); | ||
754 | up(&u132->scheduler_lock); | ||
755 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
756 | return; | ||
757 | } else if (endp->dequeueing) { | ||
758 | endp->dequeueing = 0; | ||
759 | up(&u132->scheduler_lock); | ||
760 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
761 | return; | ||
762 | } else if (u132->going > 0) { | ||
763 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
764 | "%p status=%d\n", urb, urb->status); | ||
765 | up(&u132->scheduler_lock); | ||
766 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
767 | return; | ||
768 | } else if (urb->status == -EINPROGRESS) { | ||
769 | struct u132_ring *ring = endp->ring; | ||
770 | urb->actual_length += len; | ||
771 | endp->toggle_bits = toggle_bits; | ||
772 | if (urb->transfer_buffer_length > urb->actual_length) { | ||
773 | int retval; | ||
774 | up(&u132->scheduler_lock); | ||
775 | retval = edset_output(u132, ring, endp, urb, address, | ||
776 | endp->toggle_bits, u132_hcd_bulk_output_sent); | ||
777 | if (retval == 0) { | ||
778 | } else | ||
779 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
780 | return; | ||
781 | } else { | ||
782 | up(&u132->scheduler_lock); | ||
783 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
784 | return; | ||
785 | } | ||
786 | } else { | ||
787 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
788 | "s=%d\n", urb, urb->status); | ||
789 | up(&u132->scheduler_lock); | ||
790 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
791 | return; | ||
792 | } | ||
793 | } | ||
794 | |||
795 | static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf, | ||
796 | int len, int toggle_bits, int error_count, int condition_code, | ||
797 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
798 | { | ||
799 | struct u132_endp *endp = data; | ||
800 | struct u132 *u132 = endp->u132; | ||
801 | u8 address = u132->addr[endp->usb_addr].address; | ||
802 | struct u132_udev *udev = &u132->udev[address]; | ||
803 | down(&u132->scheduler_lock); | ||
804 | if (u132->going > 1) { | ||
805 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
806 | , u132->going); | ||
807 | up(&u132->scheduler_lock); | ||
808 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
809 | return; | ||
810 | } else if (endp->dequeueing) { | ||
811 | endp->dequeueing = 0; | ||
812 | up(&u132->scheduler_lock); | ||
813 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
814 | return; | ||
815 | } else if (u132->going > 0) { | ||
816 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
817 | "%p status=%d\n", urb, urb->status); | ||
818 | up(&u132->scheduler_lock); | ||
819 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
820 | return; | ||
821 | } else if (urb->status == -EINPROGRESS) { | ||
822 | struct u132_ring *ring = endp->ring; | ||
823 | u8 *u = urb->transfer_buffer + urb->actual_length; | ||
824 | u8 *b = buf; | ||
825 | int L = len; | ||
826 | while (L-- > 0) { | ||
827 | *u++ = *b++; | ||
828 | } | ||
829 | urb->actual_length += len; | ||
830 | if ((condition_code == TD_CC_NOERROR) && | ||
831 | (urb->transfer_buffer_length > urb->actual_length)) { | ||
832 | int retval; | ||
833 | endp->toggle_bits = toggle_bits; | ||
834 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, | ||
835 | 1 & toggle_bits); | ||
836 | up(&u132->scheduler_lock); | ||
837 | retval = usb_ftdi_elan_edset_input(u132->platform_dev, | ||
838 | ring->number, endp, urb, address, | ||
839 | endp->usb_endp, endp->toggle_bits, | ||
840 | u132_hcd_bulk_input_recv); | ||
841 | if (retval == 0) { | ||
842 | } else | ||
843 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
844 | return; | ||
845 | } else if (condition_code == TD_CC_NOERROR) { | ||
846 | endp->toggle_bits = toggle_bits; | ||
847 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, | ||
848 | 1 & toggle_bits); | ||
849 | up(&u132->scheduler_lock); | ||
850 | u132_hcd_giveback_urb(u132, endp, urb, | ||
851 | cc_to_error[condition_code]); | ||
852 | return; | ||
853 | } else if ((condition_code == TD_DATAUNDERRUN) && | ||
854 | ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) { | ||
855 | endp->toggle_bits = toggle_bits; | ||
856 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, | ||
857 | 1 & toggle_bits); | ||
858 | up(&u132->scheduler_lock); | ||
859 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
860 | return; | ||
861 | } else if (condition_code == TD_DATAUNDERRUN) { | ||
862 | endp->toggle_bits = toggle_bits; | ||
863 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, | ||
864 | 1 & toggle_bits); | ||
865 | dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK" | ||
866 | ") giving back BULK IN %s\n", urb, | ||
867 | cc_to_text[condition_code]); | ||
868 | up(&u132->scheduler_lock); | ||
869 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
870 | return; | ||
871 | } else if (condition_code == TD_CC_STALL) { | ||
872 | endp->toggle_bits = 0x2; | ||
873 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0); | ||
874 | up(&u132->scheduler_lock); | ||
875 | u132_hcd_giveback_urb(u132, endp, urb, | ||
876 | cc_to_error[condition_code]); | ||
877 | return; | ||
878 | } else { | ||
879 | endp->toggle_bits = 0x2; | ||
880 | usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0); | ||
881 | dev_err(&u132->platform_dev->dev, "urb=%p giving back B" | ||
882 | "ULK IN code=%d %s\n", urb, condition_code, | ||
883 | cc_to_text[condition_code]); | ||
884 | up(&u132->scheduler_lock); | ||
885 | u132_hcd_giveback_urb(u132, endp, urb, | ||
886 | cc_to_error[condition_code]); | ||
887 | return; | ||
888 | } | ||
889 | } else { | ||
890 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
891 | "s=%d\n", urb, urb->status); | ||
892 | up(&u132->scheduler_lock); | ||
893 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
894 | return; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf, | ||
899 | int len, int toggle_bits, int error_count, int condition_code, | ||
900 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
901 | { | ||
902 | struct u132_endp *endp = data; | ||
903 | struct u132 *u132 = endp->u132; | ||
904 | down(&u132->scheduler_lock); | ||
905 | if (u132->going > 1) { | ||
906 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
907 | , u132->going); | ||
908 | up(&u132->scheduler_lock); | ||
909 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
910 | return; | ||
911 | } else if (endp->dequeueing) { | ||
912 | endp->dequeueing = 0; | ||
913 | up(&u132->scheduler_lock); | ||
914 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
915 | return; | ||
916 | } else if (u132->going > 0) { | ||
917 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
918 | "%p status=%d\n", urb, urb->status); | ||
919 | up(&u132->scheduler_lock); | ||
920 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
921 | return; | ||
922 | } else if (urb->status == -EINPROGRESS) { | ||
923 | up(&u132->scheduler_lock); | ||
924 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
925 | return; | ||
926 | } else { | ||
927 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
928 | "s=%d\n", urb, urb->status); | ||
929 | up(&u132->scheduler_lock); | ||
930 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
931 | return; | ||
932 | } | ||
933 | } | ||
934 | |||
935 | static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf, | ||
936 | int len, int toggle_bits, int error_count, int condition_code, | ||
937 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
938 | { | ||
939 | struct u132_endp *endp = data; | ||
940 | struct u132 *u132 = endp->u132; | ||
941 | u8 address = u132->addr[endp->usb_addr].address; | ||
942 | down(&u132->scheduler_lock); | ||
943 | if (u132->going > 1) { | ||
944 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
945 | , u132->going); | ||
946 | up(&u132->scheduler_lock); | ||
947 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
948 | return; | ||
949 | } else if (endp->dequeueing) { | ||
950 | endp->dequeueing = 0; | ||
951 | up(&u132->scheduler_lock); | ||
952 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
953 | return; | ||
954 | } else if (u132->going > 0) { | ||
955 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
956 | "%p status=%d\n", urb, urb->status); | ||
957 | up(&u132->scheduler_lock); | ||
958 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
959 | return; | ||
960 | } else if (urb->status == -EINPROGRESS) { | ||
961 | struct u132_ring *ring = endp->ring; | ||
962 | u8 *u = urb->transfer_buffer; | ||
963 | u8 *b = buf; | ||
964 | int L = len; | ||
965 | while (L-- > 0) { | ||
966 | *u++ = *b++; | ||
967 | } | ||
968 | urb->actual_length = len; | ||
969 | if ((condition_code == TD_CC_NOERROR) || ((condition_code == | ||
970 | TD_DATAUNDERRUN) && ((urb->transfer_flags & | ||
971 | URB_SHORT_NOT_OK) == 0))) { | ||
972 | int retval; | ||
973 | up(&u132->scheduler_lock); | ||
974 | retval = usb_ftdi_elan_edset_empty(u132->platform_dev, | ||
975 | ring->number, endp, urb, address, | ||
976 | endp->usb_endp, 0x3, | ||
977 | u132_hcd_configure_empty_sent); | ||
978 | if (retval == 0) { | ||
979 | } else | ||
980 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
981 | return; | ||
982 | } else if (condition_code == TD_CC_STALL) { | ||
983 | up(&u132->scheduler_lock); | ||
984 | dev_warn(&u132->platform_dev->dev, "giving back SETUP I" | ||
985 | "NPUT STALL urb %p\n", urb); | ||
986 | u132_hcd_giveback_urb(u132, endp, urb, | ||
987 | cc_to_error[condition_code]); | ||
988 | return; | ||
989 | } else { | ||
990 | up(&u132->scheduler_lock); | ||
991 | dev_err(&u132->platform_dev->dev, "giving back SETUP IN" | ||
992 | "PUT %s urb %p\n", cc_to_text[condition_code], | ||
993 | urb); | ||
994 | u132_hcd_giveback_urb(u132, endp, urb, | ||
995 | cc_to_error[condition_code]); | ||
996 | return; | ||
997 | } | ||
998 | } else { | ||
999 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1000 | "s=%d\n", urb, urb->status); | ||
1001 | up(&u132->scheduler_lock); | ||
1002 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1003 | return; | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf, | ||
1008 | int len, int toggle_bits, int error_count, int condition_code, | ||
1009 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
1010 | { | ||
1011 | struct u132_endp *endp = data; | ||
1012 | struct u132 *u132 = endp->u132; | ||
1013 | down(&u132->scheduler_lock); | ||
1014 | if (u132->going > 1) { | ||
1015 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1016 | , u132->going); | ||
1017 | up(&u132->scheduler_lock); | ||
1018 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
1019 | return; | ||
1020 | } else if (endp->dequeueing) { | ||
1021 | endp->dequeueing = 0; | ||
1022 | up(&u132->scheduler_lock); | ||
1023 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
1024 | return; | ||
1025 | } else if (u132->going > 0) { | ||
1026 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
1027 | "%p status=%d\n", urb, urb->status); | ||
1028 | up(&u132->scheduler_lock); | ||
1029 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
1030 | return; | ||
1031 | } else if (urb->status == -EINPROGRESS) { | ||
1032 | up(&u132->scheduler_lock); | ||
1033 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
1034 | return; | ||
1035 | } else { | ||
1036 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1037 | "s=%d\n", urb, urb->status); | ||
1038 | up(&u132->scheduler_lock); | ||
1039 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1040 | return; | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf, | ||
1045 | int len, int toggle_bits, int error_count, int condition_code, | ||
1046 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
1047 | { | ||
1048 | struct u132_endp *endp = data; | ||
1049 | struct u132 *u132 = endp->u132; | ||
1050 | u8 address = u132->addr[endp->usb_addr].address; | ||
1051 | down(&u132->scheduler_lock); | ||
1052 | if (u132->going > 1) { | ||
1053 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1054 | , u132->going); | ||
1055 | up(&u132->scheduler_lock); | ||
1056 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
1057 | return; | ||
1058 | } else if (endp->dequeueing) { | ||
1059 | endp->dequeueing = 0; | ||
1060 | up(&u132->scheduler_lock); | ||
1061 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
1062 | return; | ||
1063 | } else if (u132->going > 0) { | ||
1064 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
1065 | "%p status=%d\n", urb, urb->status); | ||
1066 | up(&u132->scheduler_lock); | ||
1067 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
1068 | return; | ||
1069 | } else if (urb->status == -EINPROGRESS) { | ||
1070 | if (usb_pipein(urb->pipe)) { | ||
1071 | int retval; | ||
1072 | struct u132_ring *ring = endp->ring; | ||
1073 | up(&u132->scheduler_lock); | ||
1074 | retval = usb_ftdi_elan_edset_input(u132->platform_dev, | ||
1075 | ring->number, endp, urb, address, | ||
1076 | endp->usb_endp, 0, | ||
1077 | u132_hcd_configure_input_recv); | ||
1078 | if (retval == 0) { | ||
1079 | } else | ||
1080 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1081 | return; | ||
1082 | } else { | ||
1083 | int retval; | ||
1084 | struct u132_ring *ring = endp->ring; | ||
1085 | up(&u132->scheduler_lock); | ||
1086 | retval = usb_ftdi_elan_edset_input(u132->platform_dev, | ||
1087 | ring->number, endp, urb, address, | ||
1088 | endp->usb_endp, 0, | ||
1089 | u132_hcd_configure_empty_recv); | ||
1090 | if (retval == 0) { | ||
1091 | } else | ||
1092 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1093 | return; | ||
1094 | } | ||
1095 | } else { | ||
1096 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1097 | "s=%d\n", urb, urb->status); | ||
1098 | up(&u132->scheduler_lock); | ||
1099 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1100 | return; | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb, | ||
1105 | u8 *buf, int len, int toggle_bits, int error_count, int condition_code, | ||
1106 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
1107 | { | ||
1108 | struct u132_endp *endp = data; | ||
1109 | struct u132 *u132 = endp->u132; | ||
1110 | u8 address = u132->addr[endp->usb_addr].address; | ||
1111 | struct u132_udev *udev = &u132->udev[address]; | ||
1112 | down(&u132->scheduler_lock); | ||
1113 | if (u132->going > 1) { | ||
1114 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1115 | , u132->going); | ||
1116 | up(&u132->scheduler_lock); | ||
1117 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
1118 | return; | ||
1119 | } else if (endp->dequeueing) { | ||
1120 | endp->dequeueing = 0; | ||
1121 | up(&u132->scheduler_lock); | ||
1122 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
1123 | return; | ||
1124 | } else if (u132->going > 0) { | ||
1125 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
1126 | "%p status=%d\n", urb, urb->status); | ||
1127 | up(&u132->scheduler_lock); | ||
1128 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
1129 | return; | ||
1130 | } else if (urb->status == -EINPROGRESS) { | ||
1131 | u132->addr[0].address = 0; | ||
1132 | endp->usb_addr = udev->usb_addr; | ||
1133 | up(&u132->scheduler_lock); | ||
1134 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
1135 | return; | ||
1136 | } else { | ||
1137 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1138 | "s=%d\n", urb, urb->status); | ||
1139 | up(&u132->scheduler_lock); | ||
1140 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1141 | return; | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb, | ||
1146 | u8 *buf, int len, int toggle_bits, int error_count, int condition_code, | ||
1147 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
1148 | { | ||
1149 | struct u132_endp *endp = data; | ||
1150 | struct u132 *u132 = endp->u132; | ||
1151 | down(&u132->scheduler_lock); | ||
1152 | if (u132->going > 1) { | ||
1153 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1154 | , u132->going); | ||
1155 | up(&u132->scheduler_lock); | ||
1156 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
1157 | return; | ||
1158 | } else if (endp->dequeueing) { | ||
1159 | endp->dequeueing = 0; | ||
1160 | up(&u132->scheduler_lock); | ||
1161 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
1162 | return; | ||
1163 | } else if (u132->going > 0) { | ||
1164 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
1165 | "%p status=%d\n", urb, urb->status); | ||
1166 | up(&u132->scheduler_lock); | ||
1167 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
1168 | return; | ||
1169 | } else if (urb->status == -EINPROGRESS) { | ||
1170 | int retval; | ||
1171 | struct u132_ring *ring = endp->ring; | ||
1172 | up(&u132->scheduler_lock); | ||
1173 | retval = usb_ftdi_elan_edset_input(u132->platform_dev, | ||
1174 | ring->number, endp, urb, 0, endp->usb_endp, 0, | ||
1175 | u132_hcd_enumeration_empty_recv); | ||
1176 | if (retval == 0) { | ||
1177 | } else | ||
1178 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1179 | return; | ||
1180 | } else { | ||
1181 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1182 | "s=%d\n", urb, urb->status); | ||
1183 | up(&u132->scheduler_lock); | ||
1184 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1185 | return; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf, | ||
1190 | int len, int toggle_bits, int error_count, int condition_code, | ||
1191 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
1192 | { | ||
1193 | struct u132_endp *endp = data; | ||
1194 | struct u132 *u132 = endp->u132; | ||
1195 | down(&u132->scheduler_lock); | ||
1196 | if (u132->going > 1) { | ||
1197 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1198 | , u132->going); | ||
1199 | up(&u132->scheduler_lock); | ||
1200 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
1201 | return; | ||
1202 | } else if (endp->dequeueing) { | ||
1203 | endp->dequeueing = 0; | ||
1204 | up(&u132->scheduler_lock); | ||
1205 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
1206 | return; | ||
1207 | } else if (u132->going > 0) { | ||
1208 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
1209 | "%p status=%d\n", urb, urb->status); | ||
1210 | up(&u132->scheduler_lock); | ||
1211 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
1212 | return; | ||
1213 | } else if (urb->status == -EINPROGRESS) { | ||
1214 | up(&u132->scheduler_lock); | ||
1215 | u132_hcd_giveback_urb(u132, endp, urb, 0); | ||
1216 | return; | ||
1217 | } else { | ||
1218 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1219 | "s=%d\n", urb, urb->status); | ||
1220 | up(&u132->scheduler_lock); | ||
1221 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1222 | return; | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf, | ||
1227 | int len, int toggle_bits, int error_count, int condition_code, | ||
1228 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
1229 | { | ||
1230 | struct u132_endp *endp = data; | ||
1231 | struct u132 *u132 = endp->u132; | ||
1232 | u8 address = u132->addr[endp->usb_addr].address; | ||
1233 | down(&u132->scheduler_lock); | ||
1234 | if (u132->going > 1) { | ||
1235 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1236 | , u132->going); | ||
1237 | up(&u132->scheduler_lock); | ||
1238 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
1239 | return; | ||
1240 | } else if (endp->dequeueing) { | ||
1241 | endp->dequeueing = 0; | ||
1242 | up(&u132->scheduler_lock); | ||
1243 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
1244 | return; | ||
1245 | } else if (u132->going > 0) { | ||
1246 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
1247 | "%p status=%d\n", urb, urb->status); | ||
1248 | up(&u132->scheduler_lock); | ||
1249 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
1250 | return; | ||
1251 | } else if (urb->status == -EINPROGRESS) { | ||
1252 | int retval; | ||
1253 | struct u132_ring *ring = endp->ring; | ||
1254 | u8 *u = urb->transfer_buffer; | ||
1255 | u8 *b = buf; | ||
1256 | int L = len; | ||
1257 | while (L-- > 0) { | ||
1258 | *u++ = *b++; | ||
1259 | } | ||
1260 | urb->actual_length = len; | ||
1261 | up(&u132->scheduler_lock); | ||
1262 | retval = usb_ftdi_elan_edset_empty(u132->platform_dev, | ||
1263 | ring->number, endp, urb, address, endp->usb_endp, 0x3, | ||
1264 | u132_hcd_initial_empty_sent); | ||
1265 | if (retval == 0) { | ||
1266 | } else | ||
1267 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1268 | return; | ||
1269 | } else { | ||
1270 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1271 | "s=%d\n", urb, urb->status); | ||
1272 | up(&u132->scheduler_lock); | ||
1273 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1274 | return; | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, | ||
1279 | int len, int toggle_bits, int error_count, int condition_code, | ||
1280 | int repeat_number, int halted, int skipped, int actual, int non_null) | ||
1281 | { | ||
1282 | struct u132_endp *endp = data; | ||
1283 | struct u132 *u132 = endp->u132; | ||
1284 | u8 address = u132->addr[endp->usb_addr].address; | ||
1285 | down(&u132->scheduler_lock); | ||
1286 | if (u132->going > 1) { | ||
1287 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1288 | , u132->going); | ||
1289 | up(&u132->scheduler_lock); | ||
1290 | u132_hcd_forget_urb(u132, endp, urb, -ENODEV); | ||
1291 | return; | ||
1292 | } else if (endp->dequeueing) { | ||
1293 | endp->dequeueing = 0; | ||
1294 | up(&u132->scheduler_lock); | ||
1295 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | ||
1296 | return; | ||
1297 | } else if (u132->going > 0) { | ||
1298 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
1299 | "%p status=%d\n", urb, urb->status); | ||
1300 | up(&u132->scheduler_lock); | ||
1301 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | ||
1302 | return; | ||
1303 | } else if (urb->status == -EINPROGRESS) { | ||
1304 | int retval; | ||
1305 | struct u132_ring *ring = endp->ring; | ||
1306 | up(&u132->scheduler_lock); | ||
1307 | retval = usb_ftdi_elan_edset_input(u132->platform_dev, | ||
1308 | ring->number, endp, urb, address, endp->usb_endp, 0, | ||
1309 | u132_hcd_initial_input_recv); | ||
1310 | if (retval == 0) { | ||
1311 | } else | ||
1312 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1313 | return; | ||
1314 | } else { | ||
1315 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | ||
1316 | "s=%d\n", urb, urb->status); | ||
1317 | up(&u132->scheduler_lock); | ||
1318 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | ||
1319 | return; | ||
1320 | } | ||
1321 | } | ||
1322 | |||
1323 | static void u132_hcd_ring_work_scheduler(void *data); | ||
1324 | static void u132_hcd_endp_work_scheduler(void *data); | ||
1325 | /* | ||
1326 | * this work function is only executed from the work queue | ||
1327 | * | ||
1328 | */ | ||
1329 | static void u132_hcd_ring_work_scheduler(void *data) | ||
1330 | { | ||
1331 | struct u132_ring *ring = data; | ||
1332 | struct u132 *u132 = ring->u132; | ||
1333 | down(&u132->scheduler_lock); | ||
1334 | if (ring->in_use) { | ||
1335 | up(&u132->scheduler_lock); | ||
1336 | u132_ring_put_kref(u132, ring); | ||
1337 | return; | ||
1338 | } else if (ring->curr_endp) { | ||
1339 | struct u132_endp *last_endp = ring->curr_endp; | ||
1340 | struct list_head *scan; | ||
1341 | struct list_head *head = &last_endp->endp_ring; | ||
1342 | unsigned long wakeup = 0; | ||
1343 | list_for_each(scan, head) { | ||
1344 | struct u132_endp *endp = list_entry(scan, | ||
1345 | struct u132_endp, endp_ring); | ||
1346 | if (endp->queue_next == endp->queue_last) { | ||
1347 | } else if ((endp->delayed == 0) | ||
1348 | || time_after_eq(jiffies, endp->jiffies)) { | ||
1349 | ring->curr_endp = endp; | ||
1350 | u132_endp_cancel_work(u132, last_endp); | ||
1351 | u132_endp_queue_work(u132, last_endp, 0); | ||
1352 | up(&u132->scheduler_lock); | ||
1353 | u132_ring_put_kref(u132, ring); | ||
1354 | return; | ||
1355 | } else { | ||
1356 | unsigned long delta = endp->jiffies - jiffies; | ||
1357 | if (delta > wakeup) | ||
1358 | wakeup = delta; | ||
1359 | } | ||
1360 | } | ||
1361 | if (last_endp->queue_next == last_endp->queue_last) { | ||
1362 | } else if ((last_endp->delayed == 0) || time_after_eq(jiffies, | ||
1363 | last_endp->jiffies)) { | ||
1364 | u132_endp_cancel_work(u132, last_endp); | ||
1365 | u132_endp_queue_work(u132, last_endp, 0); | ||
1366 | up(&u132->scheduler_lock); | ||
1367 | u132_ring_put_kref(u132, ring); | ||
1368 | return; | ||
1369 | } else { | ||
1370 | unsigned long delta = last_endp->jiffies - jiffies; | ||
1371 | if (delta > wakeup) | ||
1372 | wakeup = delta; | ||
1373 | } | ||
1374 | if (wakeup > 0) { | ||
1375 | u132_ring_requeue_work(u132, ring, wakeup); | ||
1376 | up(&u132->scheduler_lock); | ||
1377 | return; | ||
1378 | } else { | ||
1379 | up(&u132->scheduler_lock); | ||
1380 | u132_ring_put_kref(u132, ring); | ||
1381 | return; | ||
1382 | } | ||
1383 | } else { | ||
1384 | up(&u132->scheduler_lock); | ||
1385 | u132_ring_put_kref(u132, ring); | ||
1386 | return; | ||
1387 | } | ||
1388 | } | ||
1389 | |||
1390 | static void u132_hcd_endp_work_scheduler(void *data) | ||
1391 | { | ||
1392 | struct u132_ring *ring; | ||
1393 | struct u132_endp *endp = data; | ||
1394 | struct u132 *u132 = endp->u132; | ||
1395 | down(&u132->scheduler_lock); | ||
1396 | ring = endp->ring; | ||
1397 | if (endp->edset_flush) { | ||
1398 | endp->edset_flush = 0; | ||
1399 | if (endp->dequeueing) | ||
1400 | usb_ftdi_elan_edset_flush(u132->platform_dev, | ||
1401 | ring->number, endp); | ||
1402 | up(&u132->scheduler_lock); | ||
1403 | u132_endp_put_kref(u132, endp); | ||
1404 | return; | ||
1405 | } else if (endp->active) { | ||
1406 | up(&u132->scheduler_lock); | ||
1407 | u132_endp_put_kref(u132, endp); | ||
1408 | return; | ||
1409 | } else if (ring->in_use) { | ||
1410 | up(&u132->scheduler_lock); | ||
1411 | u132_endp_put_kref(u132, endp); | ||
1412 | return; | ||
1413 | } else if (endp->queue_next == endp->queue_last) { | ||
1414 | up(&u132->scheduler_lock); | ||
1415 | u132_endp_put_kref(u132, endp); | ||
1416 | return; | ||
1417 | } else if (endp->pipetype == PIPE_INTERRUPT) { | ||
1418 | u8 address = u132->addr[endp->usb_addr].address; | ||
1419 | if (ring->in_use) { | ||
1420 | up(&u132->scheduler_lock); | ||
1421 | u132_endp_put_kref(u132, endp); | ||
1422 | return; | ||
1423 | } else { | ||
1424 | int retval; | ||
1425 | struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | ||
1426 | endp->queue_next]; | ||
1427 | endp->active = 1; | ||
1428 | ring->curr_endp = endp; | ||
1429 | ring->in_use = 1; | ||
1430 | up(&u132->scheduler_lock); | ||
1431 | retval = edset_single(u132, ring, endp, urb, address, | ||
1432 | endp->toggle_bits, u132_hcd_interrupt_recv); | ||
1433 | if (retval == 0) { | ||
1434 | } else | ||
1435 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1436 | return; | ||
1437 | } | ||
1438 | } else if (endp->pipetype == PIPE_CONTROL) { | ||
1439 | u8 address = u132->addr[endp->usb_addr].address; | ||
1440 | if (ring->in_use) { | ||
1441 | up(&u132->scheduler_lock); | ||
1442 | u132_endp_put_kref(u132, endp); | ||
1443 | return; | ||
1444 | } else if (address == 0) { | ||
1445 | int retval; | ||
1446 | struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | ||
1447 | endp->queue_next]; | ||
1448 | endp->active = 1; | ||
1449 | ring->curr_endp = endp; | ||
1450 | ring->in_use = 1; | ||
1451 | up(&u132->scheduler_lock); | ||
1452 | retval = edset_setup(u132, ring, endp, urb, address, | ||
1453 | 0x2, u132_hcd_initial_setup_sent); | ||
1454 | if (retval == 0) { | ||
1455 | } else | ||
1456 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1457 | return; | ||
1458 | } else if (endp->usb_addr == 0) { | ||
1459 | int retval; | ||
1460 | struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | ||
1461 | endp->queue_next]; | ||
1462 | endp->active = 1; | ||
1463 | ring->curr_endp = endp; | ||
1464 | ring->in_use = 1; | ||
1465 | up(&u132->scheduler_lock); | ||
1466 | retval = edset_setup(u132, ring, endp, urb, 0, 0x2, | ||
1467 | u132_hcd_enumeration_address_sent); | ||
1468 | if (retval == 0) { | ||
1469 | } else | ||
1470 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1471 | return; | ||
1472 | } else { | ||
1473 | int retval; | ||
1474 | u8 address = u132->addr[endp->usb_addr].address; | ||
1475 | struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & | ||
1476 | endp->queue_next]; | ||
1477 | endp->active = 1; | ||
1478 | ring->curr_endp = endp; | ||
1479 | ring->in_use = 1; | ||
1480 | up(&u132->scheduler_lock); | ||
1481 | retval = edset_setup(u132, ring, endp, urb, address, | ||
1482 | 0x2, u132_hcd_configure_setup_sent); | ||
1483 | if (retval == 0) { | ||
1484 | } else | ||
1485 | u132_hcd_giveback_urb(u132, endp, urb, retval); | ||
1486 | return; | ||
1487 | } | ||
1488 | } else { | ||
1489 | if (endp->input) { | ||
1490 | u8 address = u132->addr[endp->usb_addr].address; | ||
1491 | if (ring->in_use) { | ||
1492 | up(&u132->scheduler_lock); | ||
1493 | u132_endp_put_kref(u132, endp); | ||
1494 | return; | ||
1495 | } else { | ||
1496 | int retval; | ||
1497 | struct urb *urb = endp->urb_list[ | ||
1498 | ENDP_QUEUE_MASK & endp->queue_next]; | ||
1499 | endp->active = 1; | ||
1500 | ring->curr_endp = endp; | ||
1501 | ring->in_use = 1; | ||
1502 | up(&u132->scheduler_lock); | ||
1503 | retval = edset_input(u132, ring, endp, urb, | ||
1504 | address, endp->toggle_bits, | ||
1505 | u132_hcd_bulk_input_recv); | ||
1506 | if (retval == 0) { | ||
1507 | } else | ||
1508 | u132_hcd_giveback_urb(u132, endp, urb, | ||
1509 | retval); | ||
1510 | return; | ||
1511 | } | ||
1512 | } else { /* output pipe */ | ||
1513 | u8 address = u132->addr[endp->usb_addr].address; | ||
1514 | if (ring->in_use) { | ||
1515 | up(&u132->scheduler_lock); | ||
1516 | u132_endp_put_kref(u132, endp); | ||
1517 | return; | ||
1518 | } else { | ||
1519 | int retval; | ||
1520 | struct urb *urb = endp->urb_list[ | ||
1521 | ENDP_QUEUE_MASK & endp->queue_next]; | ||
1522 | endp->active = 1; | ||
1523 | ring->curr_endp = endp; | ||
1524 | ring->in_use = 1; | ||
1525 | up(&u132->scheduler_lock); | ||
1526 | retval = edset_output(u132, ring, endp, urb, | ||
1527 | address, endp->toggle_bits, | ||
1528 | u132_hcd_bulk_output_sent); | ||
1529 | if (retval == 0) { | ||
1530 | } else | ||
1531 | u132_hcd_giveback_urb(u132, endp, urb, | ||
1532 | retval); | ||
1533 | return; | ||
1534 | } | ||
1535 | } | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | static void port_power(struct u132 *u132, int pn, int is_on) | ||
1540 | { | ||
1541 | u132->port[pn].power = is_on; | ||
1542 | } | ||
1543 | |||
1544 | static void u132_power(struct u132 *u132, int is_on) | ||
1545 | { | ||
1546 | struct usb_hcd *hcd = u132_to_hcd(u132) | ||
1547 | ; /* hub is inactive unless the port is powered */ | ||
1548 | if (is_on) { | ||
1549 | if (u132->power) | ||
1550 | return; | ||
1551 | u132->power = 1; | ||
1552 | hcd->self.controller->power.power_state = PMSG_ON; | ||
1553 | } else { | ||
1554 | u132->power = 0; | ||
1555 | hcd->state = HC_STATE_HALT; | ||
1556 | hcd->self.controller->power.power_state = PMSG_SUSPEND; | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | static int u132_periodic_reinit(struct u132 *u132) | ||
1561 | { | ||
1562 | int retval; | ||
1563 | u32 fi = u132->hc_fminterval & 0x03fff; | ||
1564 | u32 fit; | ||
1565 | u32 fminterval; | ||
1566 | retval = u132_read_pcimem(u132, fminterval, &fminterval); | ||
1567 | if (retval) | ||
1568 | return retval; | ||
1569 | fit = fminterval & FIT; | ||
1570 | retval = u132_write_pcimem(u132, fminterval, | ||
1571 | (fit ^ FIT) | u132->hc_fminterval); | ||
1572 | if (retval) | ||
1573 | return retval; | ||
1574 | retval = u132_write_pcimem(u132, periodicstart, | ||
1575 | ((9 *fi) / 10) & 0x3fff); | ||
1576 | if (retval) | ||
1577 | return retval; | ||
1578 | return 0; | ||
1579 | } | ||
1580 | |||
1581 | static char *hcfs2string(int state) | ||
1582 | { | ||
1583 | switch (state) { | ||
1584 | case OHCI_USB_RESET: | ||
1585 | return "reset"; | ||
1586 | case OHCI_USB_RESUME: | ||
1587 | return "resume"; | ||
1588 | case OHCI_USB_OPER: | ||
1589 | return "operational"; | ||
1590 | case OHCI_USB_SUSPEND: | ||
1591 | return "suspend"; | ||
1592 | } | ||
1593 | return "?"; | ||
1594 | } | ||
1595 | |||
1596 | static int u132_usb_reset(struct u132 *u132) | ||
1597 | { | ||
1598 | int retval; | ||
1599 | retval = u132_read_pcimem(u132, control, &u132->hc_control); | ||
1600 | if (retval) | ||
1601 | return retval; | ||
1602 | u132->hc_control &= OHCI_CTRL_RWC; | ||
1603 | retval = u132_write_pcimem(u132, control, u132->hc_control); | ||
1604 | if (retval) | ||
1605 | return retval; | ||
1606 | return 0; | ||
1607 | } | ||
1608 | |||
1609 | static int u132_init(struct u132 *u132) | ||
1610 | { | ||
1611 | int retval; | ||
1612 | u32 control; | ||
1613 | u132_disable(u132); | ||
1614 | u132->next_statechange = | ||
1615 | jiffies; /* SMM owns the HC? not for long! */ { | ||
1616 | u32 control; | ||
1617 | retval = u132_read_pcimem(u132, control, &control); | ||
1618 | if (retval) | ||
1619 | return retval; | ||
1620 | if (control & OHCI_CTRL_IR) { | ||
1621 | u32 temp = 50; | ||
1622 | retval = u132_write_pcimem(u132, intrenable, | ||
1623 | OHCI_INTR_OC); | ||
1624 | if (retval) | ||
1625 | return retval; | ||
1626 | retval = u132_write_pcimem_byte(u132, cmdstatus, | ||
1627 | OHCI_OCR); | ||
1628 | if (retval) | ||
1629 | return retval; | ||
1630 | check:{ | ||
1631 | retval = u132_read_pcimem(u132, control, | ||
1632 | &control); | ||
1633 | if (retval) | ||
1634 | return retval; | ||
1635 | } | ||
1636 | if (control & OHCI_CTRL_IR) { | ||
1637 | msleep(10); | ||
1638 | if (--temp == 0) { | ||
1639 | dev_err(&u132->platform_dev->dev, "USB " | ||
1640 | "HC takeover failed!(BIOS/SMM b" | ||
1641 | "ug) control=%08X\n", control); | ||
1642 | return -EBUSY; | ||
1643 | } | ||
1644 | goto check; | ||
1645 | } | ||
1646 | u132_usb_reset(u132); | ||
1647 | } | ||
1648 | } | ||
1649 | retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); | ||
1650 | if (retval) | ||
1651 | return retval; | ||
1652 | retval = u132_read_pcimem(u132, control, &control); | ||
1653 | if (retval) | ||
1654 | return retval; | ||
1655 | if (u132->num_ports == 0) { | ||
1656 | u32 rh_a = -1; | ||
1657 | retval = u132_read_pcimem(u132, roothub.a, &rh_a); | ||
1658 | if (retval) | ||
1659 | return retval; | ||
1660 | u132->num_ports = rh_a & RH_A_NDP; | ||
1661 | retval = read_roothub_info(u132); | ||
1662 | if (retval) | ||
1663 | return retval; | ||
1664 | } | ||
1665 | if (u132->num_ports > MAX_U132_PORTS) { | ||
1666 | return -EINVAL; | ||
1667 | } | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1671 | |||
1672 | /* Start an OHCI controller, set the BUS operational | ||
1673 | * resets USB and controller | ||
1674 | * enable interrupts | ||
1675 | */ | ||
1676 | static int u132_run(struct u132 *u132) | ||
1677 | { | ||
1678 | int retval; | ||
1679 | u32 control; | ||
1680 | u32 status; | ||
1681 | u32 fminterval; | ||
1682 | u32 periodicstart; | ||
1683 | u32 cmdstatus; | ||
1684 | u32 roothub_a; | ||
1685 | int mask = OHCI_INTR_INIT; | ||
1686 | int first = u132->hc_fminterval == 0; | ||
1687 | int sleep_time = 0; | ||
1688 | int reset_timeout = 30; /* ... allow extra time */ | ||
1689 | u132_disable(u132); | ||
1690 | if (first) { | ||
1691 | u32 temp; | ||
1692 | retval = u132_read_pcimem(u132, fminterval, &temp); | ||
1693 | if (retval) | ||
1694 | return retval; | ||
1695 | u132->hc_fminterval = temp & 0x3fff; | ||
1696 | if (u132->hc_fminterval != FI) { | ||
1697 | } | ||
1698 | u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16; | ||
1699 | } | ||
1700 | retval = u132_read_pcimem(u132, control, &u132->hc_control); | ||
1701 | if (retval) | ||
1702 | return retval; | ||
1703 | dev_info(&u132->platform_dev->dev, "resetting from state '%s', control " | ||
1704 | "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS), | ||
1705 | u132->hc_control); | ||
1706 | switch (u132->hc_control & OHCI_CTRL_HCFS) { | ||
1707 | case OHCI_USB_OPER: | ||
1708 | sleep_time = 0; | ||
1709 | break; | ||
1710 | case OHCI_USB_SUSPEND: | ||
1711 | case OHCI_USB_RESUME: | ||
1712 | u132->hc_control &= OHCI_CTRL_RWC; | ||
1713 | u132->hc_control |= OHCI_USB_RESUME; | ||
1714 | sleep_time = 10; | ||
1715 | break; | ||
1716 | default: | ||
1717 | u132->hc_control &= OHCI_CTRL_RWC; | ||
1718 | u132->hc_control |= OHCI_USB_RESET; | ||
1719 | sleep_time = 50; | ||
1720 | break; | ||
1721 | } | ||
1722 | retval = u132_write_pcimem(u132, control, u132->hc_control); | ||
1723 | if (retval) | ||
1724 | return retval; | ||
1725 | retval = u132_read_pcimem(u132, control, &control); | ||
1726 | if (retval) | ||
1727 | return retval; | ||
1728 | msleep(sleep_time); | ||
1729 | retval = u132_read_pcimem(u132, roothub.a, &roothub_a); | ||
1730 | if (retval) | ||
1731 | return retval; | ||
1732 | if (!(roothub_a & RH_A_NPS)) { | ||
1733 | int temp; /* power down each port */ | ||
1734 | for (temp = 0; temp < u132->num_ports; temp++) { | ||
1735 | retval = u132_write_pcimem(u132, | ||
1736 | roothub.portstatus[temp], RH_PS_LSDA); | ||
1737 | if (retval) | ||
1738 | return retval; | ||
1739 | } | ||
1740 | } | ||
1741 | retval = u132_read_pcimem(u132, control, &control); | ||
1742 | if (retval) | ||
1743 | return retval; | ||
1744 | retry:retval = u132_read_pcimem(u132, cmdstatus, &status); | ||
1745 | if (retval) | ||
1746 | return retval; | ||
1747 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR); | ||
1748 | if (retval) | ||
1749 | return retval; | ||
1750 | extra:{ | ||
1751 | retval = u132_read_pcimem(u132, cmdstatus, &status); | ||
1752 | if (retval) | ||
1753 | return retval; | ||
1754 | if (0 != (status & OHCI_HCR)) { | ||
1755 | if (--reset_timeout == 0) { | ||
1756 | dev_err(&u132->platform_dev->dev, "USB HC reset" | ||
1757 | " timed out!\n"); | ||
1758 | return -ENODEV; | ||
1759 | } else { | ||
1760 | msleep(5); | ||
1761 | goto extra; | ||
1762 | } | ||
1763 | } | ||
1764 | } | ||
1765 | if (u132->flags & OHCI_QUIRK_INITRESET) { | ||
1766 | retval = u132_write_pcimem(u132, control, u132->hc_control); | ||
1767 | if (retval) | ||
1768 | return retval; | ||
1769 | retval = u132_read_pcimem(u132, control, &control); | ||
1770 | if (retval) | ||
1771 | return retval; | ||
1772 | } | ||
1773 | retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000); | ||
1774 | if (retval) | ||
1775 | return retval; | ||
1776 | retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000); | ||
1777 | if (retval) | ||
1778 | return retval; | ||
1779 | retval = u132_write_pcimem(u132, hcca, 0x00000000); | ||
1780 | if (retval) | ||
1781 | return retval; | ||
1782 | retval = u132_periodic_reinit(u132); | ||
1783 | if (retval) | ||
1784 | return retval; | ||
1785 | retval = u132_read_pcimem(u132, fminterval, &fminterval); | ||
1786 | if (retval) | ||
1787 | return retval; | ||
1788 | retval = u132_read_pcimem(u132, periodicstart, &periodicstart); | ||
1789 | if (retval) | ||
1790 | return retval; | ||
1791 | if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) { | ||
1792 | if (!(u132->flags & OHCI_QUIRK_INITRESET)) { | ||
1793 | u132->flags |= OHCI_QUIRK_INITRESET; | ||
1794 | goto retry; | ||
1795 | } else | ||
1796 | dev_err(&u132->platform_dev->dev, "init err(%08x %04x)" | ||
1797 | "\n", fminterval, periodicstart); | ||
1798 | } /* start controller operations */ | ||
1799 | u132->hc_control &= OHCI_CTRL_RWC; | ||
1800 | u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER; | ||
1801 | retval = u132_write_pcimem(u132, control, u132->hc_control); | ||
1802 | if (retval) | ||
1803 | return retval; | ||
1804 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF); | ||
1805 | if (retval) | ||
1806 | return retval; | ||
1807 | retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); | ||
1808 | if (retval) | ||
1809 | return retval; | ||
1810 | retval = u132_read_pcimem(u132, control, &control); | ||
1811 | if (retval) | ||
1812 | return retval; | ||
1813 | u132_to_hcd(u132)->state = HC_STATE_RUNNING; | ||
1814 | retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE); | ||
1815 | if (retval) | ||
1816 | return retval; | ||
1817 | retval = u132_write_pcimem(u132, intrstatus, mask); | ||
1818 | if (retval) | ||
1819 | return retval; | ||
1820 | retval = u132_write_pcimem(u132, intrdisable, | ||
1821 | OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO | | ||
1822 | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH | | ||
1823 | OHCI_INTR_SO); | ||
1824 | if (retval) | ||
1825 | return retval; /* handle root hub init quirks ... */ | ||
1826 | retval = u132_read_pcimem(u132, roothub.a, &roothub_a); | ||
1827 | if (retval) | ||
1828 | return retval; | ||
1829 | roothub_a &= ~(RH_A_PSM | RH_A_OCPM); | ||
1830 | if (u132->flags & OHCI_QUIRK_SUPERIO) { | ||
1831 | roothub_a |= RH_A_NOCP; | ||
1832 | roothub_a &= ~(RH_A_POTPGT | RH_A_NPS); | ||
1833 | retval = u132_write_pcimem(u132, roothub.a, roothub_a); | ||
1834 | if (retval) | ||
1835 | return retval; | ||
1836 | } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) { | ||
1837 | roothub_a |= RH_A_NPS; | ||
1838 | retval = u132_write_pcimem(u132, roothub.a, roothub_a); | ||
1839 | if (retval) | ||
1840 | return retval; | ||
1841 | } | ||
1842 | retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC); | ||
1843 | if (retval) | ||
1844 | return retval; | ||
1845 | retval = u132_write_pcimem(u132, roothub.b, | ||
1846 | (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM); | ||
1847 | if (retval) | ||
1848 | return retval; | ||
1849 | retval = u132_read_pcimem(u132, control, &control); | ||
1850 | if (retval) | ||
1851 | return retval; | ||
1852 | mdelay((roothub_a >> 23) & 0x1fe); | ||
1853 | u132_to_hcd(u132)->state = HC_STATE_RUNNING; | ||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static void u132_hcd_stop(struct usb_hcd *hcd) | ||
1858 | { | ||
1859 | struct u132 *u132 = hcd_to_u132(hcd); | ||
1860 | if (u132->going > 1) { | ||
1861 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1862 | , u132->going); | ||
1863 | } else if (u132->going > 0) { | ||
1864 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | ||
1865 | "ed\n", hcd); | ||
1866 | } else { | ||
1867 | down(&u132->sw_lock); | ||
1868 | msleep(100); | ||
1869 | u132_power(u132, 0); | ||
1870 | up(&u132->sw_lock); | ||
1871 | } | ||
1872 | } | ||
1873 | |||
1874 | static int u132_hcd_start(struct usb_hcd *hcd) | ||
1875 | { | ||
1876 | struct u132 *u132 = hcd_to_u132(hcd); | ||
1877 | if (u132->going > 1) { | ||
1878 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1879 | , u132->going); | ||
1880 | return -ENODEV; | ||
1881 | } else if (u132->going > 0) { | ||
1882 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
1883 | return -ESHUTDOWN; | ||
1884 | } else if (hcd->self.controller) { | ||
1885 | int retval; | ||
1886 | struct platform_device *pdev = | ||
1887 | to_platform_device(hcd->self.controller); | ||
1888 | u16 vendor = ((struct u132_platform_data *) | ||
1889 | (pdev->dev.platform_data))->vendor; | ||
1890 | u16 device = ((struct u132_platform_data *) | ||
1891 | (pdev->dev.platform_data))->device; | ||
1892 | down(&u132->sw_lock); | ||
1893 | msleep(10); | ||
1894 | if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) { | ||
1895 | u132->flags = OHCI_QUIRK_AMD756; | ||
1896 | } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) { | ||
1897 | dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar" | ||
1898 | "ounds unavailable\n"); | ||
1899 | } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8) | ||
1900 | u132->flags |= OHCI_QUIRK_ZFMICRO; | ||
1901 | retval = u132_run(u132); | ||
1902 | if (retval) { | ||
1903 | u132_disable(u132); | ||
1904 | u132->going = 1; | ||
1905 | } | ||
1906 | msleep(100); | ||
1907 | up(&u132->sw_lock); | ||
1908 | return retval; | ||
1909 | } else { | ||
1910 | dev_err(&u132->platform_dev->dev, "platform_device missing\n"); | ||
1911 | return -ENODEV; | ||
1912 | } | ||
1913 | } | ||
1914 | |||
1915 | static int u132_hcd_reset(struct usb_hcd *hcd) | ||
1916 | { | ||
1917 | struct u132 *u132 = hcd_to_u132(hcd); | ||
1918 | if (u132->going > 1) { | ||
1919 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
1920 | , u132->going); | ||
1921 | return -ENODEV; | ||
1922 | } else if (u132->going > 0) { | ||
1923 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
1924 | return -ESHUTDOWN; | ||
1925 | } else { | ||
1926 | int retval; | ||
1927 | down(&u132->sw_lock); | ||
1928 | retval = u132_init(u132); | ||
1929 | if (retval) { | ||
1930 | u132_disable(u132); | ||
1931 | u132->going = 1; | ||
1932 | } | ||
1933 | up(&u132->sw_lock); | ||
1934 | return retval; | ||
1935 | } | ||
1936 | } | ||
1937 | |||
1938 | static int create_endpoint_and_queue_int(struct u132 *u132, | ||
1939 | struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb, | ||
1940 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, | ||
1941 | gfp_t mem_flags) | ||
1942 | { | ||
1943 | struct u132_ring *ring; | ||
1944 | unsigned long irqs; | ||
1945 | u8 endp_number = ++u132->num_endpoints; | ||
1946 | struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | ||
1947 | kmalloc(sizeof(struct u132_endp), mem_flags); | ||
1948 | if (!endp) { | ||
1949 | return -ENOMEM; | ||
1950 | } | ||
1951 | INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); | ||
1952 | spin_lock_init(&endp->queue_lock.slock); | ||
1953 | INIT_LIST_HEAD(&endp->urb_more); | ||
1954 | ring = endp->ring = &u132->ring[0]; | ||
1955 | if (ring->curr_endp) { | ||
1956 | list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring); | ||
1957 | } else { | ||
1958 | INIT_LIST_HEAD(&endp->endp_ring); | ||
1959 | ring->curr_endp = endp; | ||
1960 | } | ||
1961 | ring->length += 1; | ||
1962 | endp->dequeueing = 0; | ||
1963 | endp->edset_flush = 0; | ||
1964 | endp->active = 0; | ||
1965 | endp->delayed = 0; | ||
1966 | endp->endp_number = endp_number; | ||
1967 | endp->u132 = u132; | ||
1968 | endp->hep = hep; | ||
1969 | endp->pipetype = usb_pipetype(urb->pipe); | ||
1970 | u132_endp_init_kref(u132, endp); | ||
1971 | if (usb_pipein(urb->pipe)) { | ||
1972 | endp->toggle_bits = 0x2; | ||
1973 | usb_settoggle(udev->usb_device, usb_endp, 0, 0); | ||
1974 | endp->input = 1; | ||
1975 | endp->output = 0; | ||
1976 | udev->endp_number_in[usb_endp] = endp_number; | ||
1977 | u132_udev_get_kref(u132, udev); | ||
1978 | } else { | ||
1979 | endp->toggle_bits = 0x2; | ||
1980 | usb_settoggle(udev->usb_device, usb_endp, 1, 0); | ||
1981 | endp->input = 0; | ||
1982 | endp->output = 1; | ||
1983 | udev->endp_number_out[usb_endp] = endp_number; | ||
1984 | u132_udev_get_kref(u132, udev); | ||
1985 | } | ||
1986 | urb->hcpriv = u132; | ||
1987 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
1988 | endp->delayed = 1; | ||
1989 | endp->jiffies = jiffies + msecs_to_jiffies(urb->interval); | ||
1990 | endp->udev_number = address; | ||
1991 | endp->usb_addr = usb_addr; | ||
1992 | endp->usb_endp = usb_endp; | ||
1993 | endp->queue_size = 1; | ||
1994 | endp->queue_last = 0; | ||
1995 | endp->queue_next = 0; | ||
1996 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | ||
1997 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
1998 | u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval)); | ||
1999 | return 0; | ||
2000 | } | ||
2001 | |||
2002 | static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | ||
2003 | struct usb_host_endpoint *hep, struct urb *urb, | ||
2004 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | ||
2005 | u8 usb_endp, u8 address) | ||
2006 | { | ||
2007 | urb->hcpriv = u132; | ||
2008 | endp->delayed = 1; | ||
2009 | endp->jiffies = jiffies + msecs_to_jiffies(urb->interval); | ||
2010 | if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | ||
2011 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | ||
2012 | } else { | ||
2013 | struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq), | ||
2014 | GFP_ATOMIC); | ||
2015 | if (urbq == NULL) { | ||
2016 | endp->queue_size -= 1; | ||
2017 | return -ENOMEM; | ||
2018 | } else { | ||
2019 | list_add_tail(&urbq->urb_more, &endp->urb_more); | ||
2020 | urbq->urb = urb; | ||
2021 | } | ||
2022 | } | ||
2023 | return 0; | ||
2024 | } | ||
2025 | |||
2026 | static int create_endpoint_and_queue_bulk(struct u132 *u132, | ||
2027 | struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb, | ||
2028 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, | ||
2029 | gfp_t mem_flags) | ||
2030 | { | ||
2031 | int ring_number; | ||
2032 | struct u132_ring *ring; | ||
2033 | unsigned long irqs; | ||
2034 | u8 endp_number = ++u132->num_endpoints; | ||
2035 | struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | ||
2036 | kmalloc(sizeof(struct u132_endp), mem_flags); | ||
2037 | if (!endp) { | ||
2038 | return -ENOMEM; | ||
2039 | } | ||
2040 | INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); | ||
2041 | spin_lock_init(&endp->queue_lock.slock); | ||
2042 | INIT_LIST_HEAD(&endp->urb_more); | ||
2043 | endp->dequeueing = 0; | ||
2044 | endp->edset_flush = 0; | ||
2045 | endp->active = 0; | ||
2046 | endp->delayed = 0; | ||
2047 | endp->endp_number = endp_number; | ||
2048 | endp->u132 = u132; | ||
2049 | endp->hep = hep; | ||
2050 | endp->pipetype = usb_pipetype(urb->pipe); | ||
2051 | u132_endp_init_kref(u132, endp); | ||
2052 | if (usb_pipein(urb->pipe)) { | ||
2053 | endp->toggle_bits = 0x2; | ||
2054 | usb_settoggle(udev->usb_device, usb_endp, 0, 0); | ||
2055 | ring_number = 3; | ||
2056 | endp->input = 1; | ||
2057 | endp->output = 0; | ||
2058 | udev->endp_number_in[usb_endp] = endp_number; | ||
2059 | u132_udev_get_kref(u132, udev); | ||
2060 | } else { | ||
2061 | endp->toggle_bits = 0x2; | ||
2062 | usb_settoggle(udev->usb_device, usb_endp, 1, 0); | ||
2063 | ring_number = 2; | ||
2064 | endp->input = 0; | ||
2065 | endp->output = 1; | ||
2066 | udev->endp_number_out[usb_endp] = endp_number; | ||
2067 | u132_udev_get_kref(u132, udev); | ||
2068 | } | ||
2069 | ring = endp->ring = &u132->ring[ring_number - 1]; | ||
2070 | if (ring->curr_endp) { | ||
2071 | list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring); | ||
2072 | } else { | ||
2073 | INIT_LIST_HEAD(&endp->endp_ring); | ||
2074 | ring->curr_endp = endp; | ||
2075 | } | ||
2076 | ring->length += 1; | ||
2077 | urb->hcpriv = u132; | ||
2078 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2079 | endp->udev_number = address; | ||
2080 | endp->usb_addr = usb_addr; | ||
2081 | endp->usb_endp = usb_endp; | ||
2082 | endp->queue_size = 1; | ||
2083 | endp->queue_last = 0; | ||
2084 | endp->queue_next = 0; | ||
2085 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | ||
2086 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2087 | u132_endp_queue_work(u132, endp, 0); | ||
2088 | return 0; | ||
2089 | } | ||
2090 | |||
2091 | static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | ||
2092 | struct usb_host_endpoint *hep, struct urb *urb, | ||
2093 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | ||
2094 | u8 usb_endp, u8 address) | ||
2095 | { | ||
2096 | urb->hcpriv = u132; | ||
2097 | if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | ||
2098 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | ||
2099 | } else { | ||
2100 | struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq), | ||
2101 | GFP_ATOMIC); | ||
2102 | if (urbq == NULL) { | ||
2103 | endp->queue_size -= 1; | ||
2104 | return -ENOMEM; | ||
2105 | } else { | ||
2106 | list_add_tail(&urbq->urb_more, &endp->urb_more); | ||
2107 | urbq->urb = urb; | ||
2108 | } | ||
2109 | } | ||
2110 | return 0; | ||
2111 | } | ||
2112 | |||
2113 | static int create_endpoint_and_queue_control(struct u132 *u132, | ||
2114 | struct usb_host_endpoint *hep, struct urb *urb, | ||
2115 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, | ||
2116 | gfp_t mem_flags) | ||
2117 | { | ||
2118 | struct u132_ring *ring; | ||
2119 | u8 endp_number = ++u132->num_endpoints; | ||
2120 | struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | ||
2121 | kmalloc(sizeof(struct u132_endp), mem_flags); | ||
2122 | if (!endp) { | ||
2123 | return -ENOMEM; | ||
2124 | } | ||
2125 | INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); | ||
2126 | spin_lock_init(&endp->queue_lock.slock); | ||
2127 | INIT_LIST_HEAD(&endp->urb_more); | ||
2128 | ring = endp->ring = &u132->ring[0]; | ||
2129 | if (ring->curr_endp) { | ||
2130 | list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring); | ||
2131 | } else { | ||
2132 | INIT_LIST_HEAD(&endp->endp_ring); | ||
2133 | ring->curr_endp = endp; | ||
2134 | } | ||
2135 | ring->length += 1; | ||
2136 | endp->dequeueing = 0; | ||
2137 | endp->edset_flush = 0; | ||
2138 | endp->active = 0; | ||
2139 | endp->delayed = 0; | ||
2140 | endp->endp_number = endp_number; | ||
2141 | endp->u132 = u132; | ||
2142 | endp->hep = hep; | ||
2143 | u132_endp_init_kref(u132, endp); | ||
2144 | u132_endp_get_kref(u132, endp); | ||
2145 | if (usb_addr == 0) { | ||
2146 | unsigned long irqs; | ||
2147 | u8 address = u132->addr[usb_addr].address; | ||
2148 | struct u132_udev *udev = &u132->udev[address]; | ||
2149 | endp->udev_number = address; | ||
2150 | endp->usb_addr = usb_addr; | ||
2151 | endp->usb_endp = usb_endp; | ||
2152 | endp->input = 1; | ||
2153 | endp->output = 1; | ||
2154 | endp->pipetype = usb_pipetype(urb->pipe); | ||
2155 | u132_udev_init_kref(u132, udev); | ||
2156 | u132_udev_get_kref(u132, udev); | ||
2157 | udev->endp_number_in[usb_endp] = endp_number; | ||
2158 | udev->endp_number_out[usb_endp] = endp_number; | ||
2159 | urb->hcpriv = u132; | ||
2160 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2161 | endp->queue_size = 1; | ||
2162 | endp->queue_last = 0; | ||
2163 | endp->queue_next = 0; | ||
2164 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | ||
2165 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2166 | u132_endp_queue_work(u132, endp, 0); | ||
2167 | return 0; | ||
2168 | } else { /*(usb_addr > 0) */ | ||
2169 | unsigned long irqs; | ||
2170 | u8 address = u132->addr[usb_addr].address; | ||
2171 | struct u132_udev *udev = &u132->udev[address]; | ||
2172 | endp->udev_number = address; | ||
2173 | endp->usb_addr = usb_addr; | ||
2174 | endp->usb_endp = usb_endp; | ||
2175 | endp->input = 1; | ||
2176 | endp->output = 1; | ||
2177 | endp->pipetype = usb_pipetype(urb->pipe); | ||
2178 | u132_udev_get_kref(u132, udev); | ||
2179 | udev->enumeration = 2; | ||
2180 | udev->endp_number_in[usb_endp] = endp_number; | ||
2181 | udev->endp_number_out[usb_endp] = endp_number; | ||
2182 | urb->hcpriv = u132; | ||
2183 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2184 | endp->queue_size = 1; | ||
2185 | endp->queue_last = 0; | ||
2186 | endp->queue_next = 0; | ||
2187 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb; | ||
2188 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2189 | u132_endp_queue_work(u132, endp, 0); | ||
2190 | return 0; | ||
2191 | } | ||
2192 | } | ||
2193 | |||
2194 | static int queue_control_on_old_endpoint(struct u132 *u132, | ||
2195 | struct usb_host_endpoint *hep, struct urb *urb, | ||
2196 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | ||
2197 | u8 usb_endp) | ||
2198 | { | ||
2199 | if (usb_addr == 0) { | ||
2200 | if (usb_pipein(urb->pipe)) { | ||
2201 | urb->hcpriv = u132; | ||
2202 | if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | ||
2203 | endp->urb_list[ENDP_QUEUE_MASK & | ||
2204 | endp->queue_last++] = urb; | ||
2205 | } else { | ||
2206 | struct u132_urbq *urbq = | ||
2207 | kmalloc(sizeof(struct u132_urbq), | ||
2208 | GFP_ATOMIC); | ||
2209 | if (urbq == NULL) { | ||
2210 | endp->queue_size -= 1; | ||
2211 | return -ENOMEM; | ||
2212 | } else { | ||
2213 | list_add_tail(&urbq->urb_more, | ||
2214 | &endp->urb_more); | ||
2215 | urbq->urb = urb; | ||
2216 | } | ||
2217 | } | ||
2218 | return 0; | ||
2219 | } else { /* usb_pipeout(urb->pipe) */ | ||
2220 | struct u132_addr *addr = &u132->addr[usb_dev->devnum]; | ||
2221 | int I = MAX_U132_UDEVS; | ||
2222 | int i = 0; | ||
2223 | while (--I > 0) { | ||
2224 | struct u132_udev *udev = &u132->udev[++i]; | ||
2225 | if (udev->usb_device) { | ||
2226 | continue; | ||
2227 | } else { | ||
2228 | udev->enumeration = 1; | ||
2229 | u132->addr[0].address = i; | ||
2230 | endp->udev_number = i; | ||
2231 | udev->udev_number = i; | ||
2232 | udev->usb_addr = usb_dev->devnum; | ||
2233 | u132_udev_init_kref(u132, udev); | ||
2234 | udev->endp_number_in[usb_endp] = | ||
2235 | endp->endp_number; | ||
2236 | u132_udev_get_kref(u132, udev); | ||
2237 | udev->endp_number_out[usb_endp] = | ||
2238 | endp->endp_number; | ||
2239 | udev->usb_device = usb_dev; | ||
2240 | ((u8 *) (urb->setup_packet))[2] = | ||
2241 | addr->address = i; | ||
2242 | u132_udev_get_kref(u132, udev); | ||
2243 | break; | ||
2244 | } | ||
2245 | } | ||
2246 | if (I == 0) { | ||
2247 | dev_err(&u132->platform_dev->dev, "run out of d" | ||
2248 | "evice space\n"); | ||
2249 | return -EINVAL; | ||
2250 | } | ||
2251 | urb->hcpriv = u132; | ||
2252 | if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | ||
2253 | endp->urb_list[ENDP_QUEUE_MASK & | ||
2254 | endp->queue_last++] = urb; | ||
2255 | } else { | ||
2256 | struct u132_urbq *urbq = | ||
2257 | kmalloc(sizeof(struct u132_urbq), | ||
2258 | GFP_ATOMIC); | ||
2259 | if (urbq == NULL) { | ||
2260 | endp->queue_size -= 1; | ||
2261 | return -ENOMEM; | ||
2262 | } else { | ||
2263 | list_add_tail(&urbq->urb_more, | ||
2264 | &endp->urb_more); | ||
2265 | urbq->urb = urb; | ||
2266 | } | ||
2267 | } | ||
2268 | return 0; | ||
2269 | } | ||
2270 | } else { /*(usb_addr > 0) */ | ||
2271 | u8 address = u132->addr[usb_addr].address; | ||
2272 | struct u132_udev *udev = &u132->udev[address]; | ||
2273 | urb->hcpriv = u132; | ||
2274 | if (udev->enumeration == 2) { | ||
2275 | } else | ||
2276 | udev->enumeration = 2; | ||
2277 | if (endp->queue_size++ < ENDP_QUEUE_SIZE) { | ||
2278 | endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = | ||
2279 | urb; | ||
2280 | } else { | ||
2281 | struct u132_urbq *urbq = | ||
2282 | kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC); | ||
2283 | if (urbq == NULL) { | ||
2284 | endp->queue_size -= 1; | ||
2285 | return -ENOMEM; | ||
2286 | } else { | ||
2287 | list_add_tail(&urbq->urb_more, &endp->urb_more); | ||
2288 | urbq->urb = urb; | ||
2289 | } | ||
2290 | } | ||
2291 | return 0; | ||
2292 | } | ||
2293 | } | ||
2294 | |||
2295 | static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | ||
2296 | struct urb *urb, gfp_t mem_flags) | ||
2297 | { | ||
2298 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2299 | if (irqs_disabled()) { | ||
2300 | if (__GFP_WAIT & mem_flags) { | ||
2301 | printk(KERN_ERR "invalid context for function that migh" | ||
2302 | "t sleep\n"); | ||
2303 | return -EINVAL; | ||
2304 | } | ||
2305 | } | ||
2306 | if (u132->going > 1) { | ||
2307 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2308 | , u132->going); | ||
2309 | return -ENODEV; | ||
2310 | } else if (u132->going > 0) { | ||
2311 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | ||
2312 | "%p status=%d\n", urb, urb->status); | ||
2313 | return -ESHUTDOWN; | ||
2314 | } else { | ||
2315 | u8 usb_addr = usb_pipedevice(urb->pipe); | ||
2316 | u8 usb_endp = usb_pipeendpoint(urb->pipe); | ||
2317 | struct usb_device *usb_dev = urb->dev; | ||
2318 | if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { | ||
2319 | u8 address = u132->addr[usb_addr].address; | ||
2320 | struct u132_udev *udev = &u132->udev[address]; | ||
2321 | struct u132_endp *endp = hep->hcpriv; | ||
2322 | urb->actual_length = 0; | ||
2323 | if (endp) { | ||
2324 | unsigned long irqs; | ||
2325 | int retval; | ||
2326 | spin_lock_irqsave(&endp->queue_lock.slock, | ||
2327 | irqs); | ||
2328 | retval = queue_int_on_old_endpoint(u132, udev, | ||
2329 | hep, urb, usb_dev, endp, usb_addr, | ||
2330 | usb_endp, address); | ||
2331 | spin_unlock_irqrestore(&endp->queue_lock.slock, | ||
2332 | irqs); | ||
2333 | if (retval) { | ||
2334 | return retval; | ||
2335 | } else { | ||
2336 | u132_endp_queue_work(u132, endp, | ||
2337 | msecs_to_jiffies(urb->interval)) | ||
2338 | ; | ||
2339 | return 0; | ||
2340 | } | ||
2341 | } else if (u132->num_endpoints == MAX_U132_ENDPS) { | ||
2342 | return -EINVAL; | ||
2343 | } else { /*(endp == NULL) */ | ||
2344 | return create_endpoint_and_queue_int(u132, udev, | ||
2345 | hep, urb, usb_dev, usb_addr, usb_endp, | ||
2346 | address, mem_flags); | ||
2347 | } | ||
2348 | } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { | ||
2349 | dev_err(&u132->platform_dev->dev, "the hardware does no" | ||
2350 | "t support PIPE_ISOCHRONOUS\n"); | ||
2351 | return -EINVAL; | ||
2352 | } else if (usb_pipetype(urb->pipe) == PIPE_BULK) { | ||
2353 | u8 address = u132->addr[usb_addr].address; | ||
2354 | struct u132_udev *udev = &u132->udev[address]; | ||
2355 | struct u132_endp *endp = hep->hcpriv; | ||
2356 | urb->actual_length = 0; | ||
2357 | if (endp) { | ||
2358 | unsigned long irqs; | ||
2359 | int retval; | ||
2360 | spin_lock_irqsave(&endp->queue_lock.slock, | ||
2361 | irqs); | ||
2362 | retval = queue_bulk_on_old_endpoint(u132, udev, | ||
2363 | hep, urb, usb_dev, endp, usb_addr, | ||
2364 | usb_endp, address); | ||
2365 | spin_unlock_irqrestore(&endp->queue_lock.slock, | ||
2366 | irqs); | ||
2367 | if (retval) { | ||
2368 | return retval; | ||
2369 | } else { | ||
2370 | u132_endp_queue_work(u132, endp, 0); | ||
2371 | return 0; | ||
2372 | } | ||
2373 | } else if (u132->num_endpoints == MAX_U132_ENDPS) { | ||
2374 | return -EINVAL; | ||
2375 | } else | ||
2376 | return create_endpoint_and_queue_bulk(u132, | ||
2377 | udev, hep, urb, usb_dev, usb_addr, | ||
2378 | usb_endp, address, mem_flags); | ||
2379 | } else { | ||
2380 | struct u132_endp *endp = hep->hcpriv; | ||
2381 | u16 urb_size = 8; | ||
2382 | u8 *b = urb->setup_packet; | ||
2383 | int i = 0; | ||
2384 | char data[30 *3 + 4]; | ||
2385 | char *d = data; | ||
2386 | int m = (sizeof(data) - 1) / 3; | ||
2387 | int l = 0; | ||
2388 | data[0] = 0; | ||
2389 | while (urb_size-- > 0) { | ||
2390 | if (i > m) { | ||
2391 | } else if (i++ < m) { | ||
2392 | int w = sprintf(d, " %02X", *b++); | ||
2393 | d += w; | ||
2394 | l += w; | ||
2395 | } else | ||
2396 | d += sprintf(d, " .."); | ||
2397 | } | ||
2398 | if (endp) { | ||
2399 | unsigned long irqs; | ||
2400 | int retval; | ||
2401 | spin_lock_irqsave(&endp->queue_lock.slock, | ||
2402 | irqs); | ||
2403 | retval = queue_control_on_old_endpoint(u132, | ||
2404 | hep, urb, usb_dev, endp, usb_addr, | ||
2405 | usb_endp); | ||
2406 | spin_unlock_irqrestore(&endp->queue_lock.slock, | ||
2407 | irqs); | ||
2408 | if (retval) { | ||
2409 | return retval; | ||
2410 | } else { | ||
2411 | u132_endp_queue_work(u132, endp, 0); | ||
2412 | return 0; | ||
2413 | } | ||
2414 | } else if (u132->num_endpoints == MAX_U132_ENDPS) { | ||
2415 | return -EINVAL; | ||
2416 | } else | ||
2417 | return create_endpoint_and_queue_control(u132, | ||
2418 | hep, urb, usb_dev, usb_addr, usb_endp, | ||
2419 | mem_flags); | ||
2420 | } | ||
2421 | } | ||
2422 | } | ||
2423 | |||
2424 | static int dequeue_from_overflow_chain(struct u132 *u132, | ||
2425 | struct u132_endp *endp, struct urb *urb) | ||
2426 | { | ||
2427 | struct list_head *scan; | ||
2428 | struct list_head *head = &endp->urb_more; | ||
2429 | list_for_each(scan, head) { | ||
2430 | struct u132_urbq *urbq = list_entry(scan, struct u132_urbq, | ||
2431 | urb_more); | ||
2432 | if (urbq->urb == urb) { | ||
2433 | struct usb_hcd *hcd = u132_to_hcd(u132); | ||
2434 | list_del(scan); | ||
2435 | endp->queue_size -= 1; | ||
2436 | urb->error_count = 0; | ||
2437 | urb->hcpriv = NULL; | ||
2438 | usb_hcd_giveback_urb(hcd, urb, NULL); | ||
2439 | return 0; | ||
2440 | } else | ||
2441 | continue; | ||
2442 | } | ||
2443 | dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring" | ||
2444 | "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X" | ||
2445 | "\n", urb, endp->endp_number, endp, endp->ring->number, | ||
2446 | endp->input ? 'I' : ' ', endp->output ? 'O' : ' ', | ||
2447 | endp->usb_endp, endp->usb_addr, endp->queue_size, | ||
2448 | endp->queue_next, endp->queue_last); | ||
2449 | return -EINVAL; | ||
2450 | } | ||
2451 | |||
2452 | static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | ||
2453 | struct urb *urb) | ||
2454 | { | ||
2455 | unsigned long irqs; | ||
2456 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2457 | if (endp->queue_size == 0) { | ||
2458 | dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]" | ||
2459 | "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb, | ||
2460 | endp->endp_number, endp, endp->ring->number, | ||
2461 | endp->input ? 'I' : ' ', endp->output ? 'O' : ' ', | ||
2462 | endp->usb_endp, endp->usb_addr); | ||
2463 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2464 | return -EINVAL; | ||
2465 | } | ||
2466 | if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) { | ||
2467 | if (endp->active) { | ||
2468 | endp->dequeueing = 1; | ||
2469 | endp->edset_flush = 1; | ||
2470 | u132_endp_queue_work(u132, endp, 0); | ||
2471 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2472 | urb->hcpriv = NULL; | ||
2473 | return 0; | ||
2474 | } else { | ||
2475 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2476 | u132_hcd_abandon_urb(u132, endp, urb, urb->status); | ||
2477 | return 0; | ||
2478 | } | ||
2479 | } else { | ||
2480 | u16 queue_list = 0; | ||
2481 | u16 queue_size = endp->queue_size; | ||
2482 | u16 queue_scan = endp->queue_next; | ||
2483 | struct urb **urb_slot = NULL; | ||
2484 | while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) { | ||
2485 | if (urb == endp->urb_list[ENDP_QUEUE_MASK & | ||
2486 | ++queue_scan]) { | ||
2487 | urb_slot = &endp->urb_list[ENDP_QUEUE_MASK & | ||
2488 | queue_scan]; | ||
2489 | break; | ||
2490 | } else | ||
2491 | continue; | ||
2492 | } | ||
2493 | while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) { | ||
2494 | *urb_slot = endp->urb_list[ENDP_QUEUE_MASK & | ||
2495 | ++queue_scan]; | ||
2496 | urb_slot = &endp->urb_list[ENDP_QUEUE_MASK & | ||
2497 | queue_scan]; | ||
2498 | } | ||
2499 | if (urb_slot) { | ||
2500 | struct usb_hcd *hcd = u132_to_hcd(u132); | ||
2501 | endp->queue_size -= 1; | ||
2502 | if (list_empty(&endp->urb_more)) { | ||
2503 | spin_unlock_irqrestore(&endp->queue_lock.slock, | ||
2504 | irqs); | ||
2505 | } else { | ||
2506 | struct list_head *next = endp->urb_more.next; | ||
2507 | struct u132_urbq *urbq = list_entry(next, | ||
2508 | struct u132_urbq, urb_more); | ||
2509 | list_del(next); | ||
2510 | *urb_slot = urbq->urb; | ||
2511 | spin_unlock_irqrestore(&endp->queue_lock.slock, | ||
2512 | irqs); | ||
2513 | kfree(urbq); | ||
2514 | } urb->error_count = 0; | ||
2515 | urb->hcpriv = NULL; | ||
2516 | usb_hcd_giveback_urb(hcd, urb, NULL); | ||
2517 | return 0; | ||
2518 | } else if (list_empty(&endp->urb_more)) { | ||
2519 | dev_err(&u132->platform_dev->dev, "urb=%p not found in " | ||
2520 | "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr" | ||
2521 | "=%d size=%d next=%04X last=%04X\n", urb, | ||
2522 | endp->endp_number, endp, endp->ring->number, | ||
2523 | endp->input ? 'I' : ' ', | ||
2524 | endp->output ? 'O' : ' ', endp->usb_endp, | ||
2525 | endp->usb_addr, endp->queue_size, | ||
2526 | endp->queue_next, endp->queue_last); | ||
2527 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2528 | return -EINVAL; | ||
2529 | } else { | ||
2530 | int retval = dequeue_from_overflow_chain(u132, endp, | ||
2531 | urb); | ||
2532 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2533 | return retval; | ||
2534 | } | ||
2535 | } | ||
2536 | } | ||
2537 | |||
2538 | static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | ||
2539 | { | ||
2540 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2541 | if (u132->going > 2) { | ||
2542 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2543 | , u132->going); | ||
2544 | return -ENODEV; | ||
2545 | } else { | ||
2546 | u8 usb_addr = usb_pipedevice(urb->pipe); | ||
2547 | u8 usb_endp = usb_pipeendpoint(urb->pipe); | ||
2548 | u8 address = u132->addr[usb_addr].address; | ||
2549 | struct u132_udev *udev = &u132->udev[address]; | ||
2550 | if (usb_pipein(urb->pipe)) { | ||
2551 | u8 endp_number = udev->endp_number_in[usb_endp]; | ||
2552 | struct u132_endp *endp = u132->endp[endp_number - 1]; | ||
2553 | return u132_endp_urb_dequeue(u132, endp, urb); | ||
2554 | } else { | ||
2555 | u8 endp_number = udev->endp_number_out[usb_endp]; | ||
2556 | struct u132_endp *endp = u132->endp[endp_number - 1]; | ||
2557 | return u132_endp_urb_dequeue(u132, endp, urb); | ||
2558 | } | ||
2559 | } | ||
2560 | } | ||
2561 | |||
2562 | static void u132_endpoint_disable(struct usb_hcd *hcd, | ||
2563 | struct usb_host_endpoint *hep) | ||
2564 | { | ||
2565 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2566 | if (u132->going > 2) { | ||
2567 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2568 | , u132->going); | ||
2569 | } else { | ||
2570 | struct u132_endp *endp = hep->hcpriv; | ||
2571 | if (endp) | ||
2572 | u132_endp_put_kref(u132, endp); | ||
2573 | } | ||
2574 | } | ||
2575 | |||
2576 | static int u132_get_frame(struct usb_hcd *hcd) | ||
2577 | { | ||
2578 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2579 | if (u132->going > 1) { | ||
2580 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2581 | , u132->going); | ||
2582 | return -ENODEV; | ||
2583 | } else if (u132->going > 0) { | ||
2584 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
2585 | return -ESHUTDOWN; | ||
2586 | } else { | ||
2587 | int frame = 0; | ||
2588 | dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n"); | ||
2589 | msleep(100); | ||
2590 | return frame; | ||
2591 | } | ||
2592 | } | ||
2593 | |||
2594 | static int u132_roothub_descriptor(struct u132 *u132, | ||
2595 | struct usb_hub_descriptor *desc) | ||
2596 | { | ||
2597 | int retval; | ||
2598 | u16 temp; | ||
2599 | u32 rh_a = -1; | ||
2600 | u32 rh_b = -1; | ||
2601 | retval = u132_read_pcimem(u132, roothub.a, &rh_a); | ||
2602 | if (retval) | ||
2603 | return retval; | ||
2604 | desc->bDescriptorType = 0x29; | ||
2605 | desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24; | ||
2606 | desc->bHubContrCurrent = 0; | ||
2607 | desc->bNbrPorts = u132->num_ports; | ||
2608 | temp = 1 + (u132->num_ports / 8); | ||
2609 | desc->bDescLength = 7 + 2 *temp; | ||
2610 | temp = 0; | ||
2611 | if (rh_a & RH_A_NPS) | ||
2612 | temp |= 0x0002; | ||
2613 | if (rh_a & RH_A_PSM) | ||
2614 | temp |= 0x0001; | ||
2615 | if (rh_a & RH_A_NOCP) { | ||
2616 | temp |= 0x0010; | ||
2617 | } else if (rh_a & RH_A_OCPM) | ||
2618 | temp |= 0x0008; | ||
2619 | desc->wHubCharacteristics = cpu_to_le16(temp); | ||
2620 | retval = u132_read_pcimem(u132, roothub.b, &rh_b); | ||
2621 | if (retval) | ||
2622 | return retval; | ||
2623 | memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); | ||
2624 | desc->bitmap[0] = rh_b & RH_B_DR; | ||
2625 | if (u132->num_ports > 7) { | ||
2626 | desc->bitmap[1] = (rh_b & RH_B_DR) >> 8; | ||
2627 | desc->bitmap[2] = 0xff; | ||
2628 | } else | ||
2629 | desc->bitmap[1] = 0xff; | ||
2630 | return 0; | ||
2631 | } | ||
2632 | |||
2633 | static int u132_roothub_status(struct u132 *u132, __le32 *desc) | ||
2634 | { | ||
2635 | u32 rh_status = -1; | ||
2636 | int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status); | ||
2637 | *desc = cpu_to_le32(rh_status); | ||
2638 | return ret_status; | ||
2639 | } | ||
2640 | |||
2641 | static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex) | ||
2642 | { | ||
2643 | if (wIndex == 0 || wIndex > u132->num_ports) { | ||
2644 | return -EINVAL; | ||
2645 | } else { | ||
2646 | int port = wIndex - 1; | ||
2647 | u32 rh_portstatus = -1; | ||
2648 | int ret_portstatus = u132_read_pcimem(u132, | ||
2649 | roothub.portstatus[port], &rh_portstatus); | ||
2650 | *desc = cpu_to_le32(rh_portstatus); | ||
2651 | if (*(u16 *) (desc + 2)) { | ||
2652 | dev_info(&u132->platform_dev->dev, "Port %d Status Chan" | ||
2653 | "ge = %08X\n", port, *desc); | ||
2654 | } | ||
2655 | return ret_portstatus; | ||
2656 | } | ||
2657 | } | ||
2658 | |||
2659 | |||
2660 | /* this timer value might be vendor-specific ... */ | ||
2661 | #define PORT_RESET_HW_MSEC 10 | ||
2662 | #define PORT_RESET_MSEC 10 | ||
2663 | /* wrap-aware logic morphed from <linux/jiffies.h> */ | ||
2664 | #define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0) | ||
2665 | static int u132_roothub_portreset(struct u132 *u132, int port_index) | ||
2666 | { | ||
2667 | int retval; | ||
2668 | u32 fmnumber; | ||
2669 | u16 now; | ||
2670 | u16 reset_done; | ||
2671 | retval = u132_read_pcimem(u132, fmnumber, &fmnumber); | ||
2672 | if (retval) | ||
2673 | return retval; | ||
2674 | now = fmnumber; | ||
2675 | reset_done = now + PORT_RESET_MSEC; | ||
2676 | do { | ||
2677 | u32 portstat; | ||
2678 | do { | ||
2679 | retval = u132_read_pcimem(u132, | ||
2680 | roothub.portstatus[port_index], &portstat); | ||
2681 | if (retval) | ||
2682 | return retval; | ||
2683 | if (RH_PS_PRS & portstat) { | ||
2684 | continue; | ||
2685 | } else | ||
2686 | break; | ||
2687 | } while (tick_before(now, reset_done)); | ||
2688 | if (RH_PS_PRS & portstat) | ||
2689 | return -ENODEV; | ||
2690 | if (RH_PS_CCS & portstat) { | ||
2691 | if (RH_PS_PRSC & portstat) { | ||
2692 | retval = u132_write_pcimem(u132, | ||
2693 | roothub.portstatus[port_index], | ||
2694 | RH_PS_PRSC); | ||
2695 | if (retval) | ||
2696 | return retval; | ||
2697 | } | ||
2698 | } else | ||
2699 | break; /* start the next reset, | ||
2700 | sleep till it's probably done */ | ||
2701 | retval = u132_write_pcimem(u132, roothub.portstatus[port_index], | ||
2702 | RH_PS_PRS); | ||
2703 | if (retval) | ||
2704 | return retval; | ||
2705 | msleep(PORT_RESET_HW_MSEC); | ||
2706 | retval = u132_read_pcimem(u132, fmnumber, &fmnumber); | ||
2707 | if (retval) | ||
2708 | return retval; | ||
2709 | now = fmnumber; | ||
2710 | } while (tick_before(now, reset_done)); | ||
2711 | return 0; | ||
2712 | } | ||
2713 | |||
2714 | static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue, | ||
2715 | u16 wIndex) | ||
2716 | { | ||
2717 | if (wIndex == 0 || wIndex > u132->num_ports) { | ||
2718 | return -EINVAL; | ||
2719 | } else { | ||
2720 | int retval; | ||
2721 | int port_index = wIndex - 1; | ||
2722 | struct u132_port *port = &u132->port[port_index]; | ||
2723 | port->Status &= ~(1 << wValue); | ||
2724 | switch (wValue) { | ||
2725 | case USB_PORT_FEAT_SUSPEND: | ||
2726 | retval = u132_write_pcimem(u132, | ||
2727 | roothub.portstatus[port_index], RH_PS_PSS); | ||
2728 | if (retval) | ||
2729 | return retval; | ||
2730 | return 0; | ||
2731 | case USB_PORT_FEAT_POWER: | ||
2732 | retval = u132_write_pcimem(u132, | ||
2733 | roothub.portstatus[port_index], RH_PS_PPS); | ||
2734 | if (retval) | ||
2735 | return retval; | ||
2736 | return 0; | ||
2737 | case USB_PORT_FEAT_RESET: | ||
2738 | retval = u132_roothub_portreset(u132, port_index); | ||
2739 | if (retval) | ||
2740 | return retval; | ||
2741 | return 0; | ||
2742 | default: | ||
2743 | return -EPIPE; | ||
2744 | } | ||
2745 | } | ||
2746 | } | ||
2747 | |||
2748 | static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue, | ||
2749 | u16 wIndex) | ||
2750 | { | ||
2751 | if (wIndex == 0 || wIndex > u132->num_ports) { | ||
2752 | return -EINVAL; | ||
2753 | } else { | ||
2754 | int port_index = wIndex - 1; | ||
2755 | u32 temp; | ||
2756 | int retval; | ||
2757 | struct u132_port *port = &u132->port[port_index]; | ||
2758 | port->Status &= ~(1 << wValue); | ||
2759 | switch (wValue) { | ||
2760 | case USB_PORT_FEAT_ENABLE: | ||
2761 | temp = RH_PS_CCS; | ||
2762 | break; | ||
2763 | case USB_PORT_FEAT_C_ENABLE: | ||
2764 | temp = RH_PS_PESC; | ||
2765 | break; | ||
2766 | case USB_PORT_FEAT_SUSPEND: | ||
2767 | temp = RH_PS_POCI; | ||
2768 | if ((u132->hc_control & OHCI_CTRL_HCFS) | ||
2769 | != OHCI_USB_OPER) { | ||
2770 | dev_err(&u132->platform_dev->dev, "TODO resume_" | ||
2771 | "root_hub\n"); | ||
2772 | } | ||
2773 | break; | ||
2774 | case USB_PORT_FEAT_C_SUSPEND: | ||
2775 | temp = RH_PS_PSSC; | ||
2776 | break; | ||
2777 | case USB_PORT_FEAT_POWER: | ||
2778 | temp = RH_PS_LSDA; | ||
2779 | break; | ||
2780 | case USB_PORT_FEAT_C_CONNECTION: | ||
2781 | temp = RH_PS_CSC; | ||
2782 | break; | ||
2783 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
2784 | temp = RH_PS_OCIC; | ||
2785 | break; | ||
2786 | case USB_PORT_FEAT_C_RESET: | ||
2787 | temp = RH_PS_PRSC; | ||
2788 | break; | ||
2789 | default: | ||
2790 | return -EPIPE; | ||
2791 | } | ||
2792 | retval = u132_write_pcimem(u132, roothub.portstatus[port_index], | ||
2793 | temp); | ||
2794 | if (retval) | ||
2795 | return retval; | ||
2796 | return 0; | ||
2797 | } | ||
2798 | } | ||
2799 | |||
2800 | |||
2801 | /* the virtual root hub timer IRQ checks for hub status*/ | ||
2802 | static int u132_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
2803 | { | ||
2804 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2805 | if (u132->going > 1) { | ||
2806 | dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov" | ||
2807 | "ed %d\n", hcd, u132->going); | ||
2808 | return -ENODEV; | ||
2809 | } else if (u132->going > 0) { | ||
2810 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | ||
2811 | "ed\n", hcd); | ||
2812 | dump_stack(); | ||
2813 | return -ESHUTDOWN; | ||
2814 | } else { | ||
2815 | int i, changed = 0, length = 1; | ||
2816 | if (u132->flags & OHCI_QUIRK_AMD756) { | ||
2817 | if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) { | ||
2818 | dev_err(&u132->platform_dev->dev, "bogus NDP, r" | ||
2819 | "ereads as NDP=%d\n", | ||
2820 | u132->hc_roothub_a & RH_A_NDP); | ||
2821 | goto done; | ||
2822 | } | ||
2823 | } | ||
2824 | if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) { | ||
2825 | buf[0] = changed = 1; | ||
2826 | } else | ||
2827 | buf[0] = 0; | ||
2828 | if (u132->num_ports > 7) { | ||
2829 | buf[1] = 0; | ||
2830 | length++; | ||
2831 | } | ||
2832 | for (i = 0; i < u132->num_ports; i++) { | ||
2833 | if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC | | ||
2834 | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | | ||
2835 | RH_PS_PRSC)) { | ||
2836 | changed = 1; | ||
2837 | if (i < 7) { | ||
2838 | buf[0] |= 1 << (i + 1); | ||
2839 | } else | ||
2840 | buf[1] |= 1 << (i - 7); | ||
2841 | continue; | ||
2842 | } | ||
2843 | if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) { | ||
2844 | continue; | ||
2845 | } | ||
2846 | if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) { | ||
2847 | continue; | ||
2848 | } | ||
2849 | } | ||
2850 | done:return changed ? length : 0; | ||
2851 | } | ||
2852 | } | ||
2853 | |||
2854 | static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | ||
2855 | u16 wIndex, char *buf, u16 wLength) | ||
2856 | { | ||
2857 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2858 | if (u132->going > 1) { | ||
2859 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2860 | , u132->going); | ||
2861 | return -ENODEV; | ||
2862 | } else if (u132->going > 0) { | ||
2863 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
2864 | return -ESHUTDOWN; | ||
2865 | } else { | ||
2866 | int retval = 0; | ||
2867 | down(&u132->sw_lock); | ||
2868 | switch (typeReq) { | ||
2869 | case ClearHubFeature: | ||
2870 | switch (wValue) { | ||
2871 | case C_HUB_OVER_CURRENT: | ||
2872 | case C_HUB_LOCAL_POWER: | ||
2873 | break; | ||
2874 | default: | ||
2875 | goto stall; | ||
2876 | } | ||
2877 | break; | ||
2878 | case SetHubFeature: | ||
2879 | switch (wValue) { | ||
2880 | case C_HUB_OVER_CURRENT: | ||
2881 | case C_HUB_LOCAL_POWER: | ||
2882 | break; | ||
2883 | default: | ||
2884 | goto stall; | ||
2885 | } | ||
2886 | break; | ||
2887 | case ClearPortFeature:{ | ||
2888 | retval = u132_roothub_clearportfeature(u132, | ||
2889 | wValue, wIndex); | ||
2890 | if (retval) | ||
2891 | goto error; | ||
2892 | break; | ||
2893 | } | ||
2894 | case GetHubDescriptor:{ | ||
2895 | retval = u132_roothub_descriptor(u132, | ||
2896 | (struct usb_hub_descriptor *)buf); | ||
2897 | if (retval) | ||
2898 | goto error; | ||
2899 | break; | ||
2900 | } | ||
2901 | case GetHubStatus:{ | ||
2902 | retval = u132_roothub_status(u132, | ||
2903 | (__le32 *) buf); | ||
2904 | if (retval) | ||
2905 | goto error; | ||
2906 | break; | ||
2907 | } | ||
2908 | case GetPortStatus:{ | ||
2909 | retval = u132_roothub_portstatus(u132, | ||
2910 | (__le32 *) buf, wIndex); | ||
2911 | if (retval) | ||
2912 | goto error; | ||
2913 | break; | ||
2914 | } | ||
2915 | case SetPortFeature:{ | ||
2916 | retval = u132_roothub_setportfeature(u132, | ||
2917 | wValue, wIndex); | ||
2918 | if (retval) | ||
2919 | goto error; | ||
2920 | break; | ||
2921 | } | ||
2922 | default: | ||
2923 | goto stall; | ||
2924 | error:u132_disable(u132); | ||
2925 | u132->going = 1; | ||
2926 | break; | ||
2927 | stall:retval = -EPIPE; | ||
2928 | break; | ||
2929 | } | ||
2930 | up(&u132->sw_lock); | ||
2931 | return retval; | ||
2932 | } | ||
2933 | } | ||
2934 | |||
2935 | static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num) | ||
2936 | { | ||
2937 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2938 | if (u132->going > 1) { | ||
2939 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2940 | , u132->going); | ||
2941 | return -ENODEV; | ||
2942 | } else if (u132->going > 0) { | ||
2943 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
2944 | return -ESHUTDOWN; | ||
2945 | } else | ||
2946 | return 0; | ||
2947 | } | ||
2948 | |||
2949 | static void u132_hub_irq_enable(struct usb_hcd *hcd) | ||
2950 | { | ||
2951 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2952 | if (u132->going > 1) { | ||
2953 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2954 | , u132->going); | ||
2955 | } else if (u132->going > 0) | ||
2956 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
2957 | } | ||
2958 | |||
2959 | |||
2960 | #ifdef CONFIG_PM | ||
2961 | static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message) | ||
2962 | { | ||
2963 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2964 | if (u132->going > 1) { | ||
2965 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2966 | , u132->going); | ||
2967 | return -ENODEV; | ||
2968 | } else if (u132->going > 0) { | ||
2969 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
2970 | return -ESHUTDOWN; | ||
2971 | } else | ||
2972 | return 0; | ||
2973 | } | ||
2974 | |||
2975 | static int u132_hcd_resume(struct usb_hcd *hcd) | ||
2976 | { | ||
2977 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2978 | if (u132->going > 1) { | ||
2979 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2980 | , u132->going); | ||
2981 | return -ENODEV; | ||
2982 | } else if (u132->going > 0) { | ||
2983 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
2984 | return -ESHUTDOWN; | ||
2985 | } else | ||
2986 | return 0; | ||
2987 | } | ||
2988 | |||
2989 | static int u132_bus_suspend(struct usb_hcd *hcd) | ||
2990 | { | ||
2991 | struct u132 *u132 = hcd_to_u132(hcd); | ||
2992 | if (u132->going > 1) { | ||
2993 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
2994 | , u132->going); | ||
2995 | return -ENODEV; | ||
2996 | } else if (u132->going > 0) { | ||
2997 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
2998 | return -ESHUTDOWN; | ||
2999 | } else | ||
3000 | return 0; | ||
3001 | } | ||
3002 | |||
3003 | static int u132_bus_resume(struct usb_hcd *hcd) | ||
3004 | { | ||
3005 | struct u132 *u132 = hcd_to_u132(hcd); | ||
3006 | if (u132->going > 1) { | ||
3007 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
3008 | , u132->going); | ||
3009 | return -ENODEV; | ||
3010 | } else if (u132->going > 0) { | ||
3011 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
3012 | return -ESHUTDOWN; | ||
3013 | } else | ||
3014 | return 0; | ||
3015 | } | ||
3016 | |||
3017 | #else | ||
3018 | #define u132_hcd_suspend NULL | ||
3019 | #define u132_hcd_resume NULL | ||
3020 | #define u132_bus_suspend NULL | ||
3021 | #define u132_bus_resume NULL | ||
3022 | #endif | ||
3023 | static struct hc_driver u132_hc_driver = { | ||
3024 | .description = hcd_name, | ||
3025 | .hcd_priv_size = sizeof(struct u132), | ||
3026 | .irq = NULL, | ||
3027 | .flags = HCD_USB11 | HCD_MEMORY, | ||
3028 | .reset = u132_hcd_reset, | ||
3029 | .start = u132_hcd_start, | ||
3030 | .suspend = u132_hcd_suspend, | ||
3031 | .resume = u132_hcd_resume, | ||
3032 | .stop = u132_hcd_stop, | ||
3033 | .urb_enqueue = u132_urb_enqueue, | ||
3034 | .urb_dequeue = u132_urb_dequeue, | ||
3035 | .endpoint_disable = u132_endpoint_disable, | ||
3036 | .get_frame_number = u132_get_frame, | ||
3037 | .hub_status_data = u132_hub_status_data, | ||
3038 | .hub_control = u132_hub_control, | ||
3039 | .bus_suspend = u132_bus_suspend, | ||
3040 | .bus_resume = u132_bus_resume, | ||
3041 | .start_port_reset = u132_start_port_reset, | ||
3042 | .hub_irq_enable = u132_hub_irq_enable, | ||
3043 | }; | ||
3044 | |||
3045 | /* | ||
3046 | * This function may be called by the USB core whilst the "usb_all_devices_rwsem" | ||
3047 | * is held for writing, thus this module must not call usb_remove_hcd() | ||
3048 | * synchronously - but instead should immediately stop activity to the | ||
3049 | * device and ansynchronously call usb_remove_hcd() | ||
3050 | */ | ||
3051 | static int __devexit u132_remove(struct platform_device *pdev) | ||
3052 | { | ||
3053 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
3054 | if (hcd) { | ||
3055 | struct u132 *u132 = hcd_to_u132(hcd); | ||
3056 | dump_stack(); | ||
3057 | if (u132->going++ > 1) { | ||
3058 | return -ENODEV; | ||
3059 | } else { | ||
3060 | int rings = MAX_U132_RINGS; | ||
3061 | int endps = MAX_U132_ENDPS; | ||
3062 | msleep(100); | ||
3063 | down(&u132->sw_lock); | ||
3064 | u132_monitor_cancel_work(u132); | ||
3065 | while (rings-- > 0) { | ||
3066 | struct u132_ring *ring = &u132->ring[rings]; | ||
3067 | u132_ring_cancel_work(u132, ring); | ||
3068 | } while (endps-- > 0) { | ||
3069 | struct u132_endp *endp = u132->endp[endps]; | ||
3070 | if (endp) | ||
3071 | u132_endp_cancel_work(u132, endp); | ||
3072 | } | ||
3073 | u132->going += 1; | ||
3074 | printk(KERN_INFO "removing device u132.%d\n", | ||
3075 | u132->sequence_num); | ||
3076 | up(&u132->sw_lock); | ||
3077 | usb_remove_hcd(hcd); | ||
3078 | u132_u132_put_kref(u132); | ||
3079 | return 0; | ||
3080 | } | ||
3081 | } else | ||
3082 | return 0; | ||
3083 | } | ||
3084 | |||
3085 | static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | ||
3086 | { | ||
3087 | int rings = MAX_U132_RINGS; | ||
3088 | int ports = MAX_U132_PORTS; | ||
3089 | int addrs = MAX_U132_ADDRS; | ||
3090 | int udevs = MAX_U132_UDEVS; | ||
3091 | int endps = MAX_U132_ENDPS; | ||
3092 | u132->board = pdev->dev.platform_data; | ||
3093 | u132->platform_dev = pdev; | ||
3094 | u132->power = 0; | ||
3095 | u132->reset = 0; | ||
3096 | init_MUTEX(&u132->sw_lock); | ||
3097 | init_MUTEX(&u132->scheduler_lock); | ||
3098 | while (rings-- > 0) { | ||
3099 | struct u132_ring *ring = &u132->ring[rings]; | ||
3100 | ring->u132 = u132; | ||
3101 | ring->number = rings + 1; | ||
3102 | ring->length = 0; | ||
3103 | ring->curr_endp = NULL; | ||
3104 | INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler, | ||
3105 | (void *)ring); | ||
3106 | } down(&u132->sw_lock); | ||
3107 | INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132); | ||
3108 | while (ports-- > 0) { | ||
3109 | struct u132_port *port = &u132->port[ports]; | ||
3110 | port->u132 = u132; | ||
3111 | port->reset = 0; | ||
3112 | port->enable = 0; | ||
3113 | port->power = 0; | ||
3114 | port->Status = 0; | ||
3115 | } while (addrs-- > 0) { | ||
3116 | struct u132_addr *addr = &u132->addr[addrs]; | ||
3117 | addr->address = 0; | ||
3118 | } while (udevs-- > 0) { | ||
3119 | struct u132_udev *udev = &u132->udev[udevs]; | ||
3120 | int i = ARRAY_SIZE(udev->endp_number_in); | ||
3121 | int o = ARRAY_SIZE(udev->endp_number_out); | ||
3122 | udev->usb_device = NULL; | ||
3123 | udev->udev_number = 0; | ||
3124 | udev->usb_addr = 0; | ||
3125 | udev->portnumber = 0; | ||
3126 | while (i-- > 0) { | ||
3127 | udev->endp_number_in[i] = 0; | ||
3128 | } | ||
3129 | while (o-- > 0) { | ||
3130 | udev->endp_number_out[o] = 0; | ||
3131 | } | ||
3132 | } | ||
3133 | while (endps-- > 0) { | ||
3134 | u132->endp[endps] = NULL; | ||
3135 | } | ||
3136 | up(&u132->sw_lock); | ||
3137 | return; | ||
3138 | } | ||
3139 | |||
3140 | static int __devinit u132_probe(struct platform_device *pdev) | ||
3141 | { | ||
3142 | struct usb_hcd *hcd; | ||
3143 | msleep(100); | ||
3144 | if (u132_exiting > 0) { | ||
3145 | return -ENODEV; | ||
3146 | } /* refuse to confuse usbcore */ | ||
3147 | if (pdev->dev.dma_mask) { | ||
3148 | return -EINVAL; | ||
3149 | } | ||
3150 | hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id); | ||
3151 | if (!hcd) { | ||
3152 | printk(KERN_ERR "failed to create the usb hcd struct for U132\n" | ||
3153 | ); | ||
3154 | ftdi_elan_gone_away(pdev); | ||
3155 | return -ENOMEM; | ||
3156 | } else { | ||
3157 | int retval = 0; | ||
3158 | struct u132 *u132 = hcd_to_u132(hcd); | ||
3159 | hcd->rsrc_start = 0; | ||
3160 | down(&u132_module_lock); | ||
3161 | list_add_tail(&u132->u132_list, &u132_static_list); | ||
3162 | u132->sequence_num = ++u132_instances; | ||
3163 | up(&u132_module_lock); | ||
3164 | u132_u132_init_kref(u132); | ||
3165 | u132_initialise(u132, pdev); | ||
3166 | hcd->product_desc = "ELAN U132 Host Controller"; | ||
3167 | retval = usb_add_hcd(hcd, 0, 0); | ||
3168 | if (retval != 0) { | ||
3169 | dev_err(&u132->platform_dev->dev, "init error %d\n", | ||
3170 | retval); | ||
3171 | u132_u132_put_kref(u132); | ||
3172 | return retval; | ||
3173 | } else { | ||
3174 | u132_monitor_queue_work(u132, 100); | ||
3175 | return 0; | ||
3176 | } | ||
3177 | } | ||
3178 | } | ||
3179 | |||
3180 | |||
3181 | #ifdef CONFIG_PM | ||
3182 | /* for this device there's no useful distinction between the controller | ||
3183 | * and its root hub, except that the root hub only gets direct PM calls | ||
3184 | * when CONFIG_USB_SUSPEND is enabled. | ||
3185 | */ | ||
3186 | static int u132_suspend(struct platform_device *pdev, pm_message_t state) | ||
3187 | { | ||
3188 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
3189 | struct u132 *u132 = hcd_to_u132(hcd); | ||
3190 | if (u132->going > 1) { | ||
3191 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
3192 | , u132->going); | ||
3193 | return -ENODEV; | ||
3194 | } else if (u132->going > 0) { | ||
3195 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
3196 | return -ESHUTDOWN; | ||
3197 | } else { | ||
3198 | int retval = 0; | ||
3199 | if (state.event == PM_EVENT_FREEZE) { | ||
3200 | retval = u132_bus_suspend(hcd); | ||
3201 | } else if (state.event == PM_EVENT_SUSPEND) { | ||
3202 | int ports = MAX_U132_PORTS; | ||
3203 | while (ports-- > 0) { | ||
3204 | port_power(u132, ports, 0); | ||
3205 | } | ||
3206 | } | ||
3207 | if (retval == 0) | ||
3208 | pdev->dev.power.power_state = state; | ||
3209 | return retval; | ||
3210 | } | ||
3211 | } | ||
3212 | |||
3213 | static int u132_resume(struct platform_device *pdev) | ||
3214 | { | ||
3215 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
3216 | struct u132 *u132 = hcd_to_u132(hcd); | ||
3217 | if (u132->going > 1) { | ||
3218 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | ||
3219 | , u132->going); | ||
3220 | return -ENODEV; | ||
3221 | } else if (u132->going > 0) { | ||
3222 | dev_err(&u132->platform_dev->dev, "device is being removed\n"); | ||
3223 | return -ESHUTDOWN; | ||
3224 | } else { | ||
3225 | int retval = 0; | ||
3226 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | ||
3227 | int ports = MAX_U132_PORTS; | ||
3228 | while (ports-- > 0) { | ||
3229 | port_power(u132, ports, 1); | ||
3230 | } | ||
3231 | retval = 0; | ||
3232 | } else { | ||
3233 | pdev->dev.power.power_state = PMSG_ON; | ||
3234 | retval = u132_bus_resume(hcd); | ||
3235 | } | ||
3236 | return retval; | ||
3237 | } | ||
3238 | } | ||
3239 | |||
3240 | #else | ||
3241 | #define u132_suspend NULL | ||
3242 | #define u132_resume NULL | ||
3243 | #endif | ||
3244 | /* | ||
3245 | * this driver is loaded explicitely by ftdi_u132 | ||
3246 | * | ||
3247 | * the platform_driver struct is static because it is per type of module | ||
3248 | */ | ||
3249 | static struct platform_driver u132_platform_driver = { | ||
3250 | .probe = u132_probe, | ||
3251 | .remove = __devexit_p(u132_remove), | ||
3252 | .suspend = u132_suspend, | ||
3253 | .resume = u132_resume, | ||
3254 | .driver = { | ||
3255 | .name = (char *)hcd_name, | ||
3256 | .owner = THIS_MODULE, | ||
3257 | }, | ||
3258 | }; | ||
3259 | static int __init u132_hcd_init(void) | ||
3260 | { | ||
3261 | int retval; | ||
3262 | INIT_LIST_HEAD(&u132_static_list); | ||
3263 | u132_instances = 0; | ||
3264 | u132_exiting = 0; | ||
3265 | init_MUTEX(&u132_module_lock); | ||
3266 | if (usb_disabled()) | ||
3267 | return -ENODEV; | ||
3268 | printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__, | ||
3269 | __DATE__); | ||
3270 | workqueue = create_singlethread_workqueue("u132"); | ||
3271 | retval = platform_driver_register(&u132_platform_driver); | ||
3272 | return retval; | ||
3273 | } | ||
3274 | |||
3275 | |||
3276 | module_init(u132_hcd_init); | ||
3277 | static void __exit u132_hcd_exit(void) | ||
3278 | { | ||
3279 | struct u132 *u132; | ||
3280 | struct u132 *temp; | ||
3281 | down(&u132_module_lock); | ||
3282 | u132_exiting += 1; | ||
3283 | up(&u132_module_lock); | ||
3284 | list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) { | ||
3285 | platform_device_unregister(u132->platform_dev); | ||
3286 | } platform_driver_unregister(&u132_platform_driver); | ||
3287 | printk(KERN_INFO "u132-hcd driver deregistered\n"); | ||
3288 | wait_event(u132_hcd_wait, u132_instances == 0); | ||
3289 | flush_workqueue(workqueue); | ||
3290 | destroy_workqueue(workqueue); | ||
3291 | } | ||
3292 | |||
3293 | |||
3294 | module_exit(u132_hcd_exit); | ||
3295 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index dc286a48cafd..e345f15b7d87 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | #include "uhci-hcd.h" | 17 | #include "uhci-hcd.h" |
18 | 18 | ||
19 | #define uhci_debug_operations (* (struct file_operations *) NULL) | 19 | #define uhci_debug_operations (* (const struct file_operations *) NULL) |
20 | static struct dentry *uhci_debugfs_root; | 20 | static struct dentry *uhci_debugfs_root; |
21 | 21 | ||
22 | #ifdef DEBUG | 22 | #ifdef DEBUG |
@@ -428,7 +428,7 @@ struct uhci_debug { | |||
428 | 428 | ||
429 | static int uhci_debug_open(struct inode *inode, struct file *file) | 429 | static int uhci_debug_open(struct inode *inode, struct file *file) |
430 | { | 430 | { |
431 | struct uhci_hcd *uhci = inode->u.generic_ip; | 431 | struct uhci_hcd *uhci = inode->i_private; |
432 | struct uhci_debug *up; | 432 | struct uhci_debug *up; |
433 | int ret = -ENOMEM; | 433 | int ret = -ENOMEM; |
434 | unsigned long flags; | 434 | unsigned long flags; |
@@ -500,7 +500,7 @@ static int uhci_debug_release(struct inode *inode, struct file *file) | |||
500 | } | 500 | } |
501 | 501 | ||
502 | #undef uhci_debug_operations | 502 | #undef uhci_debug_operations |
503 | static struct file_operations uhci_debug_operations = { | 503 | static const struct file_operations uhci_debug_operations = { |
504 | .owner = THIS_MODULE, | 504 | .owner = THIS_MODULE, |
505 | .open = uhci_debug_open, | 505 | .open = uhci_debug_open, |
506 | .llseek = uhci_debug_lseek, | 506 | .llseek = uhci_debug_lseek, |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4151f618602d..eb4eab98e8bf 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -734,6 +734,10 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
734 | 734 | ||
735 | /* FIXME: Enable non-PME# remote wakeup? */ | 735 | /* FIXME: Enable non-PME# remote wakeup? */ |
736 | 736 | ||
737 | /* make sure snapshot being resumed re-enumerates everything */ | ||
738 | if (message.event == PM_EVENT_PRETHAW) | ||
739 | uhci_hc_died(uhci); | ||
740 | |||
737 | done_okay: | 741 | done_okay: |
738 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 742 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
739 | done: | 743 | done: |
@@ -909,8 +913,7 @@ static int __init uhci_hcd_init(void) | |||
909 | return 0; | 913 | return 0; |
910 | 914 | ||
911 | init_failed: | 915 | init_failed: |
912 | if (kmem_cache_destroy(uhci_up_cachep)) | 916 | kmem_cache_destroy(uhci_up_cachep); |
913 | warn("not all urb_privs were freed!"); | ||
914 | 917 | ||
915 | up_failed: | 918 | up_failed: |
916 | debugfs_remove(uhci_debugfs_root); | 919 | debugfs_remove(uhci_debugfs_root); |
@@ -926,10 +929,7 @@ errbuf_failed: | |||
926 | static void __exit uhci_hcd_cleanup(void) | 929 | static void __exit uhci_hcd_cleanup(void) |
927 | { | 930 | { |
928 | pci_unregister_driver(&uhci_pci_driver); | 931 | pci_unregister_driver(&uhci_pci_driver); |
929 | 932 | kmem_cache_destroy(uhci_up_cachep); | |
930 | if (kmem_cache_destroy(uhci_up_cachep)) | ||
931 | warn("not all urb_privs were freed!"); | ||
932 | |||
933 | debugfs_remove(uhci_debugfs_root); | 933 | debugfs_remove(uhci_debugfs_root); |
934 | kfree(errbuf); | 934 | kfree(errbuf); |
935 | } | 935 | } |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index c545ef92fe29..16fb72eb6fc9 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -84,6 +84,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, | |||
84 | unsigned long port_addr) | 84 | unsigned long port_addr) |
85 | { | 85 | { |
86 | int status; | 86 | int status; |
87 | int i; | ||
87 | 88 | ||
88 | if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) { | 89 | if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) { |
89 | CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); | 90 | CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); |
@@ -92,9 +93,14 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, | |||
92 | 93 | ||
93 | /* The controller won't actually turn off the RD bit until | 94 | /* The controller won't actually turn off the RD bit until |
94 | * it has had a chance to send a low-speed EOP sequence, | 95 | * it has had a chance to send a low-speed EOP sequence, |
95 | * which takes 3 bit times (= 2 microseconds). We'll delay | 96 | * which is supposed to take 3 bit times (= 2 microseconds). |
96 | * slightly longer for good luck. */ | 97 | * Experiments show that some controllers take longer, so |
97 | udelay(4); | 98 | * we'll poll for completion. */ |
99 | for (i = 0; i < 10; ++i) { | ||
100 | if (!(inw(port_addr) & USBPORTSC_RD)) | ||
101 | break; | ||
102 | udelay(1); | ||
103 | } | ||
98 | } | 104 | } |
99 | clear_bit(port, &uhci->resuming_ports); | 105 | clear_bit(port, &uhci->resuming_ports); |
100 | } | 106 | } |
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 08daf400f985..ca6305c1d64c 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c | |||
@@ -424,7 +424,7 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res) | |||
424 | ***************************************************************************/ | 424 | ***************************************************************************/ |
425 | 425 | ||
426 | static struct usb_driver mdc800_usb_driver; | 426 | static struct usb_driver mdc800_usb_driver; |
427 | static struct file_operations mdc800_device_ops; | 427 | static const struct file_operations mdc800_device_ops; |
428 | static struct usb_class_driver mdc800_class = { | 428 | static struct usb_class_driver mdc800_class = { |
429 | .name = "mdc800%d", | 429 | .name = "mdc800%d", |
430 | .fops = &mdc800_device_ops, | 430 | .fops = &mdc800_device_ops, |
@@ -941,7 +941,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s | |||
941 | ****************************************************************************/ | 941 | ****************************************************************************/ |
942 | 942 | ||
943 | /* File Operations of this drivers */ | 943 | /* File Operations of this drivers */ |
944 | static struct file_operations mdc800_device_ops = | 944 | static const struct file_operations mdc800_device_ops = |
945 | { | 945 | { |
946 | .owner = THIS_MODULE, | 946 | .owner = THIS_MODULE, |
947 | .read = mdc800_device_read, | 947 | .read = mdc800_device_read, |
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 650103bc9618..a102a58fe361 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -205,10 +205,12 @@ config USB_TOUCHSCREEN | |||
205 | depends on USB && INPUT | 205 | depends on USB && INPUT |
206 | ---help--- | 206 | ---help--- |
207 | USB Touchscreen driver for: | 207 | USB Touchscreen driver for: |
208 | - eGalax Touchkit USB | 208 | - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700) |
209 | - PanJit TouchSet USB | 209 | - PanJit TouchSet USB |
210 | - 3M MicroTouch USB | 210 | - 3M MicroTouch USB (EX II series) |
211 | - ITM | 211 | - ITM |
212 | - some other eTurboTouch | ||
213 | - Gunze AHL61 | ||
212 | 214 | ||
213 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 215 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
214 | a usage description and the required user-space stuff. | 216 | a usage description and the required user-space stuff. |
@@ -218,7 +220,7 @@ config USB_TOUCHSCREEN | |||
218 | 220 | ||
219 | config USB_TOUCHSCREEN_EGALAX | 221 | config USB_TOUCHSCREEN_EGALAX |
220 | default y | 222 | default y |
221 | bool "eGalax device support" if EMBEDDED | 223 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED |
222 | depends on USB_TOUCHSCREEN | 224 | depends on USB_TOUCHSCREEN |
223 | 225 | ||
224 | config USB_TOUCHSCREEN_PANJIT | 226 | config USB_TOUCHSCREEN_PANJIT |
@@ -228,7 +230,7 @@ config USB_TOUCHSCREEN_PANJIT | |||
228 | 230 | ||
229 | config USB_TOUCHSCREEN_3M | 231 | config USB_TOUCHSCREEN_3M |
230 | default y | 232 | default y |
231 | bool "3M/Microtouch device support" if EMBEDDED | 233 | bool "3M/Microtouch EX II series device support" if EMBEDDED |
232 | depends on USB_TOUCHSCREEN | 234 | depends on USB_TOUCHSCREEN |
233 | 235 | ||
234 | config USB_TOUCHSCREEN_ITM | 236 | config USB_TOUCHSCREEN_ITM |
@@ -236,6 +238,16 @@ config USB_TOUCHSCREEN_ITM | |||
236 | bool "ITM device support" if EMBEDDED | 238 | bool "ITM device support" if EMBEDDED |
237 | depends on USB_TOUCHSCREEN | 239 | depends on USB_TOUCHSCREEN |
238 | 240 | ||
241 | config USB_TOUCHSCREEN_ETURBO | ||
242 | default y | ||
243 | bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED | ||
244 | depends on USB_TOUCHSCREEN | ||
245 | |||
246 | config USB_TOUCHSCREEN_GUNZE | ||
247 | default y | ||
248 | bool "Gunze AHL61 device support" if EMBEDDED | ||
249 | depends on USB_TOUCHSCREEN | ||
250 | |||
239 | config USB_YEALINK | 251 | config USB_YEALINK |
240 | tristate "Yealink usb-p1k voip phone" | 252 | tristate "Yealink usb-p1k voip phone" |
241 | depends on USB && INPUT && EXPERIMENTAL | 253 | depends on USB && INPUT && EXPERIMENTAL |
@@ -326,3 +338,13 @@ config USB_APPLETOUCH | |||
326 | 338 | ||
327 | To compile this driver as a module, choose M here: the | 339 | To compile this driver as a module, choose M here: the |
328 | module will be called appletouch. | 340 | module will be called appletouch. |
341 | |||
342 | config USB_TRANCEVIBRATOR | ||
343 | tristate "PlayStation 2 Trance Vibrator driver support" | ||
344 | depends on USB | ||
345 | help | ||
346 | Say Y here if you want to connect a PlayStation 2 Trance Vibrator | ||
347 | device to your computer's USB port. | ||
348 | |||
349 | To compile this driver as a module, choose M here: the | ||
350 | module will be called trancevibrator. | ||
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 764114529c56..48551be324ac 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Multipart objects. | 5 | # Multipart objects. |
6 | wacom-objs := wacom_sys.o wacom_wac.o | ||
6 | usbhid-objs := hid-core.o | 7 | usbhid-objs := hid-core.o |
7 | 8 | ||
8 | # Optional parts of multipart objects. | 9 | # Optional parts of multipart objects. |
@@ -44,6 +45,7 @@ obj-$(CONFIG_USB_ACECAD) += acecad.o | |||
44 | obj-$(CONFIG_USB_YEALINK) += yealink.o | 45 | obj-$(CONFIG_USB_YEALINK) += yealink.o |
45 | obj-$(CONFIG_USB_XPAD) += xpad.o | 46 | obj-$(CONFIG_USB_XPAD) += xpad.o |
46 | obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o | 47 | obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o |
48 | obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o | ||
47 | 49 | ||
48 | ifeq ($(CONFIG_USB_DEBUG),y) | 50 | ifeq ($(CONFIG_USB_DEBUG),y) |
49 | EXTRA_CFLAGS += -DDEBUG | 51 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index 18c10e150ef3..d83603ba40ae 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c | |||
@@ -141,10 +141,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ | |||
141 | 141 | ||
142 | endpoint = &interface->endpoint[0].desc; | 142 | endpoint = &interface->endpoint[0].desc; |
143 | 143 | ||
144 | if (!(endpoint->bEndpointAddress & 0x80)) | 144 | if (!usb_endpoint_is_int_in(endpoint)) |
145 | return -ENODEV; | ||
146 | |||
147 | if ((endpoint->bmAttributes & 3) != 3) | ||
148 | return -ENODEV; | 145 | return -ENODEV; |
149 | 146 | ||
150 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | 147 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); |
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index 044faa07e297..0aa9cc2bfd69 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c | |||
@@ -436,10 +436,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
436 | iface_desc = iface->cur_altsetting; | 436 | iface_desc = iface->cur_altsetting; |
437 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | 437 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { |
438 | endpoint = &iface_desc->endpoint[i].desc; | 438 | endpoint = &iface_desc->endpoint[i].desc; |
439 | if (!int_in_endpointAddr && | 439 | if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) { |
440 | (endpoint->bEndpointAddress & USB_DIR_IN) && | ||
441 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
442 | == USB_ENDPOINT_XFER_INT)) { | ||
443 | /* we found an interrupt in endpoint */ | 440 | /* we found an interrupt in endpoint */ |
444 | int_in_endpointAddr = endpoint->bEndpointAddress; | 441 | int_in_endpointAddr = endpoint->bEndpointAddress; |
445 | break; | 442 | break; |
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 3719fcb04b8f..3558d7ed99b9 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c | |||
@@ -732,12 +732,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
732 | endpoint_in = &iface_host->endpoint[0].desc; | 732 | endpoint_in = &iface_host->endpoint[0].desc; |
733 | endpoint_out = &iface_host->endpoint[1].desc; | 733 | endpoint_out = &iface_host->endpoint[1].desc; |
734 | 734 | ||
735 | if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) { | 735 | if (!usb_endpoint_is_int_in(endpoint_in)) { |
736 | err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__); | 736 | err("%s: Unexpected endpoint_in\n", __FUNCTION__); |
737 | return -ENODEV; | ||
738 | } | ||
739 | if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) { | ||
740 | err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__); | ||
741 | return -ENODEV; | 737 | return -ENODEV; |
742 | } | 738 | } |
743 | if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { | 739 | if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 3305fb6079eb..2a3e9e9b4b3d 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -1023,7 +1023,8 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs) | |||
1023 | return; | 1023 | return; |
1024 | case -EILSEQ: /* protocol error or unplug */ | 1024 | case -EILSEQ: /* protocol error or unplug */ |
1025 | case -EPROTO: /* protocol error or unplug */ | 1025 | case -EPROTO: /* protocol error or unplug */ |
1026 | case -ETIMEDOUT: /* NAK */ | 1026 | case -ETIME: /* protocol error or unplug */ |
1027 | case -ETIMEDOUT: /* Should never happen, but... */ | ||
1027 | clear_bit(HID_IN_RUNNING, &hid->iofl); | 1028 | clear_bit(HID_IN_RUNNING, &hid->iofl); |
1028 | hid_io_error(hid); | 1029 | hid_io_error(hid); |
1029 | return; | 1030 | return; |
@@ -1535,13 +1536,17 @@ void hid_init_reports(struct hid_device *hid) | |||
1535 | #define USB_VENDOR_ID_GLAB 0x06c2 | 1536 | #define USB_VENDOR_ID_GLAB 0x06c2 |
1536 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | 1537 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 |
1537 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | 1538 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 |
1538 | #define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 | ||
1539 | #define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 | 1539 | #define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 |
1540 | #define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044 | ||
1541 | #define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 | ||
1542 | #define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051 | ||
1540 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 | 1543 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 |
1544 | #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 | ||
1541 | 1545 | ||
1542 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | 1546 | #define USB_VENDOR_ID_WISEGROUP 0x0925 |
1543 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 | 1547 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 |
1544 | #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 | 1548 | #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 |
1549 | #define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 | ||
1545 | #define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 | 1550 | #define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 |
1546 | 1551 | ||
1547 | #define USB_VENDOR_ID_WISEGROUP_LTD 0x6677 | 1552 | #define USB_VENDOR_ID_WISEGROUP_LTD 0x6677 |
@@ -1591,6 +1596,10 @@ void hid_init_reports(struct hid_device *hid) | |||
1591 | 1596 | ||
1592 | #define USB_VENDOR_ID_YEALINK 0x6993 | 1597 | #define USB_VENDOR_ID_YEALINK 0x6993 |
1593 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 | 1598 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 |
1599 | |||
1600 | #define USB_VENDOR_ID_ALCOR 0x058f | ||
1601 | #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 | ||
1602 | |||
1594 | /* | 1603 | /* |
1595 | * Alphabetically sorted blacklist by quirk type. | 1604 | * Alphabetically sorted blacklist by quirk type. |
1596 | */ | 1605 | */ |
@@ -1608,6 +1617,7 @@ static const struct hid_blacklist { | |||
1608 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, | 1617 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, |
1609 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, | 1618 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, |
1610 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, | 1619 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, |
1620 | { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE }, | ||
1611 | { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, | 1621 | { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, |
1612 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, | 1622 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, |
1613 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, | 1623 | { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, |
@@ -1620,9 +1630,12 @@ static const struct hid_blacklist { | |||
1620 | { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, | 1630 | { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, |
1621 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | 1631 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, |
1622 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | 1632 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, |
1623 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
1624 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, | 1633 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, |
1634 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE }, | ||
1635 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
1636 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE }, | ||
1625 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, | 1637 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, |
1638 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE }, | ||
1626 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, | 1639 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, |
1627 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, | 1640 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, |
1628 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, | 1641 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, |
@@ -1690,7 +1703,11 @@ static const struct hid_blacklist { | |||
1690 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, | 1703 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, |
1691 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, | 1704 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, |
1692 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, | 1705 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, |
1706 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE }, | ||
1707 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE }, | ||
1693 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, | 1708 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, |
1709 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE }, | ||
1710 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE }, | ||
1694 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, | 1711 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, |
1695 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, | 1712 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, |
1696 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, | 1713 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, |
@@ -1701,6 +1718,7 @@ static const struct hid_blacklist { | |||
1701 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, | 1718 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, |
1702 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1719 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1703 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1720 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1721 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
1704 | { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, | 1722 | { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, |
1705 | 1723 | ||
1706 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, | 1724 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, |
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index f6b839c257a7..a2b419d13740 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c | |||
@@ -722,7 +722,7 @@ inval: | |||
722 | return -EINVAL; | 722 | return -EINVAL; |
723 | } | 723 | } |
724 | 724 | ||
725 | static struct file_operations hiddev_fops = { | 725 | static const struct file_operations hiddev_fops = { |
726 | .owner = THIS_MODULE, | 726 | .owner = THIS_MODULE, |
727 | .read = hiddev_read, | 727 | .read = hiddev_read, |
728 | .write = hiddev_write, | 728 | .write = hiddev_write, |
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 86acb5f1907a..61966d719ca3 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c | |||
@@ -87,7 +87,7 @@ static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) | |||
87 | case 0: | 87 | case 0: |
88 | /* success */ | 88 | /* success */ |
89 | break; | 89 | break; |
90 | case -ETIMEDOUT: | 90 | case -ETIME: |
91 | /* this urb is timing out */ | 91 | /* this urb is timing out */ |
92 | dbg("%s - urb timed out - was the device unplugged?", | 92 | dbg("%s - urb timed out - was the device unplugged?", |
93 | __FUNCTION__); | 93 | __FUNCTION__); |
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 4723b310f277..a90359551575 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c | |||
@@ -420,8 +420,7 @@ static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_i | |||
420 | for (i = 0; i < iface->desc.bNumEndpoints; ++i) { | 420 | for (i = 0; i < iface->desc.bNumEndpoints; ++i) { |
421 | endpoint = &iface->endpoint[i].desc; | 421 | endpoint = &iface->endpoint[i].desc; |
422 | 422 | ||
423 | if ((endpoint->bEndpointAddress & USB_DIR_IN) && | 423 | if (usb_endpoint_is_int_in(endpoint)) { |
424 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { | ||
425 | /* we found our interrupt in endpoint */ | 424 | /* we found our interrupt in endpoint */ |
426 | return endpoint; | 425 | return endpoint; |
427 | } | 426 | } |
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index a9ccda8810e0..5dce951f2751 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c | |||
@@ -107,7 +107,7 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) | |||
107 | case 0: | 107 | case 0: |
108 | /* success */ | 108 | /* success */ |
109 | break; | 109 | break; |
110 | case -ETIMEDOUT: | 110 | case -ETIME: |
111 | /* this urb is timing out */ | 111 | /* this urb is timing out */ |
112 | dbg("%s - urb timed out - was the device unplugged?", | 112 | dbg("%s - urb timed out - was the device unplugged?", |
113 | __FUNCTION__); | 113 | __FUNCTION__); |
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index b3c0d0c3eae9..f0f8db6810a2 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c | |||
@@ -313,9 +313,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
313 | 313 | ||
314 | interface = intf->cur_altsetting; | 314 | interface = intf->cur_altsetting; |
315 | endpoint = &interface->endpoint[0].desc; | 315 | endpoint = &interface->endpoint[0].desc; |
316 | if (!(endpoint->bEndpointAddress & 0x80)) | 316 | if (!usb_endpoint_is_int_in(endpoint)) |
317 | return -EIO; | ||
318 | if ((endpoint->bmAttributes & 3) != 3) | ||
319 | return -EIO; | 317 | return -EIO; |
320 | 318 | ||
321 | usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 319 | usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 0149043ffb97..30b9f820e7a8 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c | |||
@@ -201,7 +201,7 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs) | |||
201 | case 0: | 201 | case 0: |
202 | /* success */ | 202 | /* success */ |
203 | break; | 203 | break; |
204 | case -ETIMEDOUT: | 204 | case -ETIME: |
205 | /* this urb is timing out */ | 205 | /* this urb is timing out */ |
206 | dbg("%s - urb timed out - was the device unplugged?", | 206 | dbg("%s - urb timed out - was the device unplugged?", |
207 | __FUNCTION__); | 207 | __FUNCTION__); |
diff --git a/drivers/usb/input/trancevibrator.c b/drivers/usb/input/trancevibrator.c new file mode 100644 index 000000000000..33cd91d11eca --- /dev/null +++ b/drivers/usb/input/trancevibrator.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * PlayStation 2 Trance Vibrator driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Sam Hocevar <sam@zoy.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | /* Standard include files */ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/usb.h> | ||
27 | |||
28 | /* Version Information */ | ||
29 | #define DRIVER_VERSION "v1.1" | ||
30 | #define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org" | ||
31 | #define DRIVER_DESC "PlayStation 2 Trance Vibrator driver" | ||
32 | |||
33 | #define TRANCEVIBRATOR_VENDOR_ID 0x0b49 /* ASCII Corporation */ | ||
34 | #define TRANCEVIBRATOR_PRODUCT_ID 0x064f /* Trance Vibrator */ | ||
35 | |||
36 | static struct usb_device_id id_table [] = { | ||
37 | { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) }, | ||
38 | { }, | ||
39 | }; | ||
40 | MODULE_DEVICE_TABLE (usb, id_table); | ||
41 | |||
42 | /* Driver-local specific stuff */ | ||
43 | struct trancevibrator { | ||
44 | struct usb_device *udev; | ||
45 | unsigned int speed; | ||
46 | }; | ||
47 | |||
48 | static ssize_t show_speed(struct device *dev, struct device_attribute *attr, | ||
49 | char *buf) | ||
50 | { | ||
51 | struct usb_interface *intf = to_usb_interface(dev); | ||
52 | struct trancevibrator *tv = usb_get_intfdata(intf); | ||
53 | |||
54 | return sprintf(buf, "%d\n", tv->speed); | ||
55 | } | ||
56 | |||
57 | static ssize_t set_speed(struct device *dev, struct device_attribute *attr, | ||
58 | const char *buf, size_t count) | ||
59 | { | ||
60 | struct usb_interface *intf = to_usb_interface(dev); | ||
61 | struct trancevibrator *tv = usb_get_intfdata(intf); | ||
62 | int temp, retval; | ||
63 | |||
64 | temp = simple_strtoul(buf, NULL, 10); | ||
65 | if (temp > 255) | ||
66 | temp = 255; | ||
67 | else if (temp < 0) | ||
68 | temp = 0; | ||
69 | tv->speed = temp; | ||
70 | |||
71 | dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed); | ||
72 | |||
73 | /* Set speed */ | ||
74 | retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0), | ||
75 | 0x01, /* vendor request: set speed */ | ||
76 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
77 | tv->speed, /* speed value */ | ||
78 | 0, NULL, 0, USB_CTRL_GET_TIMEOUT); | ||
79 | if (retval) { | ||
80 | dev_dbg(&tv->udev->dev, "retval = %d\n", retval); | ||
81 | return retval; | ||
82 | } | ||
83 | return count; | ||
84 | } | ||
85 | |||
86 | static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed); | ||
87 | |||
88 | static int tv_probe(struct usb_interface *interface, | ||
89 | const struct usb_device_id *id) | ||
90 | { | ||
91 | struct usb_device *udev = interface_to_usbdev(interface); | ||
92 | struct trancevibrator *dev; | ||
93 | int retval; | ||
94 | |||
95 | dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL); | ||
96 | if (dev == NULL) { | ||
97 | dev_err(&interface->dev, "Out of memory\n"); | ||
98 | retval = -ENOMEM; | ||
99 | goto error; | ||
100 | } | ||
101 | |||
102 | dev->udev = usb_get_dev(udev); | ||
103 | usb_set_intfdata(interface, dev); | ||
104 | retval = device_create_file(&interface->dev, &dev_attr_speed); | ||
105 | if (retval) | ||
106 | goto error_create_file; | ||
107 | |||
108 | return 0; | ||
109 | |||
110 | error_create_file: | ||
111 | usb_put_dev(udev); | ||
112 | usb_set_intfdata(interface, NULL); | ||
113 | error: | ||
114 | kfree(dev); | ||
115 | return retval; | ||
116 | } | ||
117 | |||
118 | static void tv_disconnect(struct usb_interface *interface) | ||
119 | { | ||
120 | struct trancevibrator *dev; | ||
121 | |||
122 | dev = usb_get_intfdata (interface); | ||
123 | usb_set_intfdata(interface, NULL); | ||
124 | device_remove_file(&interface->dev, &dev_attr_speed); | ||
125 | usb_put_dev(dev->udev); | ||
126 | kfree(dev); | ||
127 | } | ||
128 | |||
129 | /* USB subsystem object */ | ||
130 | static struct usb_driver tv_driver = { | ||
131 | .name = "trancevibrator", | ||
132 | .probe = tv_probe, | ||
133 | .disconnect = tv_disconnect, | ||
134 | .id_table = id_table, | ||
135 | }; | ||
136 | |||
137 | static int __init tv_init(void) | ||
138 | { | ||
139 | int retval = usb_register(&tv_driver); | ||
140 | if (retval) { | ||
141 | err("usb_register failed. Error number %d", retval); | ||
142 | return retval; | ||
143 | } | ||
144 | |||
145 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static void __exit tv_exit(void) | ||
150 | { | ||
151 | usb_deregister(&tv_driver); | ||
152 | } | ||
153 | |||
154 | module_init (tv_init); | ||
155 | module_exit (tv_exit); | ||
156 | |||
157 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
158 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
159 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 446935b671d9..0fb792be95ef 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c | |||
@@ -218,7 +218,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf) | |||
218 | 218 | ||
219 | static struct usb_device_id usb_mouse_id_table [] = { | 219 | static struct usb_device_id usb_mouse_id_table [] = { |
220 | { USB_INTERFACE_INFO(3, 1, 2) }, | 220 | { USB_INTERFACE_INFO(3, 1, 2) }, |
221 | { } /* Terminating entry */ | 221 | { } /* Terminating entry */ |
222 | }; | 222 | }; |
223 | 223 | ||
224 | MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); | 224 | MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); |
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index a338bf4c2d78..4640d1000d83 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c | |||
@@ -2,9 +2,12 @@ | |||
2 | * usbtouchscreen.c | 2 | * usbtouchscreen.c |
3 | * Driver for USB Touchscreens, supporting those devices: | 3 | * Driver for USB Touchscreens, supporting those devices: |
4 | * - eGalax Touchkit | 4 | * - eGalax Touchkit |
5 | * - 3M/Microtouch | 5 | * includes eTurboTouch CT-410/510/700 |
6 | * - 3M/Microtouch EX II series | ||
6 | * - ITM | 7 | * - ITM |
7 | * - PanJit TouchSet | 8 | * - PanJit TouchSet |
9 | * - eTurboTouch | ||
10 | * - Gunze AHL61 | ||
8 | * | 11 | * |
9 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> | 12 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> |
10 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 13 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -42,7 +45,7 @@ | |||
42 | #include <linux/usb/input.h> | 45 | #include <linux/usb/input.h> |
43 | 46 | ||
44 | 47 | ||
45 | #define DRIVER_VERSION "v0.3" | 48 | #define DRIVER_VERSION "v0.4" |
46 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" | 49 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" |
47 | #define DRIVER_DESC "USB Touchscreen Driver" | 50 | #define DRIVER_DESC "USB Touchscreen Driver" |
48 | 51 | ||
@@ -60,6 +63,7 @@ struct usbtouch_device_info { | |||
60 | int flags; | 63 | int flags; |
61 | 64 | ||
62 | void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len); | 65 | void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len); |
66 | int (*get_pkt_len) (unsigned char *pkt, int len); | ||
63 | int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press); | 67 | int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press); |
64 | int (*init) (struct usbtouch_usb *usbtouch); | 68 | int (*init) (struct usbtouch_usb *usbtouch); |
65 | }; | 69 | }; |
@@ -81,8 +85,16 @@ struct usbtouch_usb { | |||
81 | char phys[64]; | 85 | char phys[64]; |
82 | }; | 86 | }; |
83 | 87 | ||
84 | static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, | 88 | |
85 | struct pt_regs *regs, unsigned char *pkt, int len); | 89 | #if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO) |
90 | #define MULTI_PACKET | ||
91 | #endif | ||
92 | |||
93 | #ifdef MULTI_PACKET | ||
94 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | ||
95 | struct pt_regs *regs, | ||
96 | unsigned char *pkt, int len); | ||
97 | #endif | ||
86 | 98 | ||
87 | /* device types */ | 99 | /* device types */ |
88 | enum { | 100 | enum { |
@@ -91,14 +103,19 @@ enum { | |||
91 | DEVTYPE_PANJIT, | 103 | DEVTYPE_PANJIT, |
92 | DEVTYPE_3M, | 104 | DEVTYPE_3M, |
93 | DEVTYPE_ITM, | 105 | DEVTYPE_ITM, |
106 | DEVTYPE_ETURBO, | ||
107 | DEVTYPE_GUNZE, | ||
94 | }; | 108 | }; |
95 | 109 | ||
96 | static struct usb_device_id usbtouch_devices[] = { | 110 | static struct usb_device_id usbtouch_devices[] = { |
97 | #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX | 111 | #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX |
98 | {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 112 | {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, |
113 | {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, | ||
99 | {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 114 | {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, |
100 | {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 115 | {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, |
101 | {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, | 116 | {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, |
117 | {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, | ||
118 | {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, | ||
102 | #endif | 119 | #endif |
103 | 120 | ||
104 | #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT | 121 | #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT |
@@ -116,6 +133,14 @@ static struct usb_device_id usbtouch_devices[] = { | |||
116 | {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, | 133 | {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, |
117 | #endif | 134 | #endif |
118 | 135 | ||
136 | #ifdef CONFIG_USB_TOUCHSCREEN_ETURBO | ||
137 | {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, | ||
138 | #endif | ||
139 | |||
140 | #ifdef CONFIG_USB_TOUCHSCREEN_GUNZE | ||
141 | {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, | ||
142 | #endif | ||
143 | |||
119 | {} | 144 | {} |
120 | }; | 145 | }; |
121 | 146 | ||
@@ -140,82 +165,23 @@ static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int | |||
140 | *touch = pkt[0] & 0x01; | 165 | *touch = pkt[0] & 0x01; |
141 | 166 | ||
142 | return 1; | 167 | return 1; |
143 | |||
144 | } | 168 | } |
145 | 169 | ||
146 | static int egalax_get_pkt_len(unsigned char *buf) | 170 | static int egalax_get_pkt_len(unsigned char *buf, int len) |
147 | { | 171 | { |
148 | switch (buf[0] & EGALAX_PKT_TYPE_MASK) { | 172 | switch (buf[0] & EGALAX_PKT_TYPE_MASK) { |
149 | case EGALAX_PKT_TYPE_REPT: | 173 | case EGALAX_PKT_TYPE_REPT: |
150 | return 5; | 174 | return 5; |
151 | 175 | ||
152 | case EGALAX_PKT_TYPE_DIAG: | 176 | case EGALAX_PKT_TYPE_DIAG: |
177 | if (len < 2) | ||
178 | return -1; | ||
179 | |||
153 | return buf[1] + 2; | 180 | return buf[1] + 2; |
154 | } | 181 | } |
155 | 182 | ||
156 | return 0; | 183 | return 0; |
157 | } | 184 | } |
158 | |||
159 | static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs, | ||
160 | unsigned char *pkt, int len) | ||
161 | { | ||
162 | unsigned char *buffer; | ||
163 | int pkt_len, buf_len, pos; | ||
164 | |||
165 | /* if the buffer contains data, append */ | ||
166 | if (unlikely(usbtouch->buf_len)) { | ||
167 | int tmp; | ||
168 | |||
169 | /* if only 1 byte in buffer, add another one to get length */ | ||
170 | if (usbtouch->buf_len == 1) | ||
171 | usbtouch->buffer[1] = pkt[0]; | ||
172 | |||
173 | pkt_len = egalax_get_pkt_len(usbtouch->buffer); | ||
174 | |||
175 | /* unknown packet: drop everything */ | ||
176 | if (!pkt_len) | ||
177 | return; | ||
178 | |||
179 | /* append, process */ | ||
180 | tmp = pkt_len - usbtouch->buf_len; | ||
181 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); | ||
182 | usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len); | ||
183 | |||
184 | buffer = pkt + tmp; | ||
185 | buf_len = len - tmp; | ||
186 | } else { | ||
187 | buffer = pkt; | ||
188 | buf_len = len; | ||
189 | } | ||
190 | |||
191 | /* only one byte left in buffer */ | ||
192 | if (unlikely(buf_len == 1)) { | ||
193 | usbtouch->buffer[0] = buffer[0]; | ||
194 | usbtouch->buf_len = 1; | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | /* loop over the buffer */ | ||
199 | pos = 0; | ||
200 | while (pos < buf_len) { | ||
201 | /* get packet len */ | ||
202 | pkt_len = egalax_get_pkt_len(buffer + pos); | ||
203 | |||
204 | /* unknown packet: drop everything */ | ||
205 | if (unlikely(!pkt_len)) | ||
206 | return; | ||
207 | |||
208 | /* full packet: process */ | ||
209 | if (likely(pkt_len <= buf_len)) { | ||
210 | usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len); | ||
211 | } else { | ||
212 | /* incomplete packet: save in buffer */ | ||
213 | memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); | ||
214 | usbtouch->buf_len = buf_len - pos; | ||
215 | } | ||
216 | pos += pkt_len; | ||
217 | } | ||
218 | } | ||
219 | #endif | 185 | #endif |
220 | 186 | ||
221 | 187 | ||
@@ -254,7 +220,7 @@ static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int | |||
254 | 220 | ||
255 | static int mtouch_init(struct usbtouch_usb *usbtouch) | 221 | static int mtouch_init(struct usbtouch_usb *usbtouch) |
256 | { | 222 | { |
257 | int ret; | 223 | int ret, i; |
258 | 224 | ||
259 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | 225 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), |
260 | MTOUCHUSB_RESET, | 226 | MTOUCHUSB_RESET, |
@@ -264,15 +230,20 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) | |||
264 | __FUNCTION__, ret); | 230 | __FUNCTION__, ret); |
265 | if (ret < 0) | 231 | if (ret < 0) |
266 | return ret; | 232 | return ret; |
267 | 233 | msleep(150); | |
268 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | 234 | |
269 | MTOUCHUSB_ASYNC_REPORT, | 235 | for (i = 0; i < 3; i++) { |
270 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 236 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), |
271 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); | 237 | MTOUCHUSB_ASYNC_REPORT, |
272 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | 238 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
273 | __FUNCTION__, ret); | 239 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); |
274 | if (ret < 0) | 240 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", |
275 | return ret; | 241 | __FUNCTION__, ret); |
242 | if (ret >= 0) | ||
243 | break; | ||
244 | if (ret != -EPIPE) | ||
245 | return ret; | ||
246 | } | ||
276 | 247 | ||
277 | return 0; | 248 | return 0; |
278 | } | 249 | } |
@@ -296,6 +267,54 @@ static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *pr | |||
296 | 267 | ||
297 | 268 | ||
298 | /***************************************************************************** | 269 | /***************************************************************************** |
270 | * eTurboTouch part | ||
271 | */ | ||
272 | #ifdef CONFIG_USB_TOUCHSCREEN_ETURBO | ||
273 | static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) | ||
274 | { | ||
275 | unsigned int shift; | ||
276 | |||
277 | /* packets should start with sync */ | ||
278 | if (!(pkt[0] & 0x80)) | ||
279 | return 0; | ||
280 | |||
281 | shift = (6 - (pkt[0] & 0x03)); | ||
282 | *x = ((pkt[3] << 7) | pkt[4]) >> shift; | ||
283 | *y = ((pkt[1] << 7) | pkt[2]) >> shift; | ||
284 | *touch = (pkt[0] & 0x10) ? 1 : 0; | ||
285 | |||
286 | return 1; | ||
287 | } | ||
288 | |||
289 | static int eturbo_get_pkt_len(unsigned char *buf, int len) | ||
290 | { | ||
291 | if (buf[0] & 0x80) | ||
292 | return 5; | ||
293 | if (buf[0] == 0x01) | ||
294 | return 3; | ||
295 | return 0; | ||
296 | } | ||
297 | #endif | ||
298 | |||
299 | |||
300 | /***************************************************************************** | ||
301 | * Gunze part | ||
302 | */ | ||
303 | #ifdef CONFIG_USB_TOUCHSCREEN_GUNZE | ||
304 | static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) | ||
305 | { | ||
306 | if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) | ||
307 | return 0; | ||
308 | |||
309 | *x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); | ||
310 | *y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); | ||
311 | *touch = pkt[0] & 0x20; | ||
312 | |||
313 | return 1; | ||
314 | } | ||
315 | #endif | ||
316 | |||
317 | /***************************************************************************** | ||
299 | * the different device descriptors | 318 | * the different device descriptors |
300 | */ | 319 | */ |
301 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 320 | static struct usbtouch_device_info usbtouch_dev_info[] = { |
@@ -307,7 +326,8 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
307 | .max_yc = 0x07ff, | 326 | .max_yc = 0x07ff, |
308 | .rept_size = 16, | 327 | .rept_size = 16, |
309 | .flags = USBTOUCH_FLG_BUFFER, | 328 | .flags = USBTOUCH_FLG_BUFFER, |
310 | .process_pkt = egalax_process, | 329 | .process_pkt = usbtouch_process_multi, |
330 | .get_pkt_len = egalax_get_pkt_len, | ||
311 | .read_data = egalax_read_data, | 331 | .read_data = egalax_read_data, |
312 | }, | 332 | }, |
313 | #endif | 333 | #endif |
@@ -346,6 +366,31 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
346 | .read_data = itm_read_data, | 366 | .read_data = itm_read_data, |
347 | }, | 367 | }, |
348 | #endif | 368 | #endif |
369 | |||
370 | #ifdef CONFIG_USB_TOUCHSCREEN_ETURBO | ||
371 | [DEVTYPE_ETURBO] = { | ||
372 | .min_xc = 0x0, | ||
373 | .max_xc = 0x07ff, | ||
374 | .min_yc = 0x0, | ||
375 | .max_yc = 0x07ff, | ||
376 | .rept_size = 8, | ||
377 | .flags = USBTOUCH_FLG_BUFFER, | ||
378 | .process_pkt = usbtouch_process_multi, | ||
379 | .get_pkt_len = eturbo_get_pkt_len, | ||
380 | .read_data = eturbo_read_data, | ||
381 | }, | ||
382 | #endif | ||
383 | |||
384 | #ifdef CONFIG_USB_TOUCHSCREEN_GUNZE | ||
385 | [DEVTYPE_GUNZE] = { | ||
386 | .min_xc = 0x0, | ||
387 | .max_xc = 0x0fff, | ||
388 | .min_yc = 0x0, | ||
389 | .max_yc = 0x0fff, | ||
390 | .rept_size = 4, | ||
391 | .read_data = gunze_read_data, | ||
392 | }, | ||
393 | #endif | ||
349 | }; | 394 | }; |
350 | 395 | ||
351 | 396 | ||
@@ -377,6 +422,83 @@ static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, | |||
377 | } | 422 | } |
378 | 423 | ||
379 | 424 | ||
425 | #ifdef MULTI_PACKET | ||
426 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | ||
427 | struct pt_regs *regs, | ||
428 | unsigned char *pkt, int len) | ||
429 | { | ||
430 | unsigned char *buffer; | ||
431 | int pkt_len, pos, buf_len, tmp; | ||
432 | |||
433 | /* process buffer */ | ||
434 | if (unlikely(usbtouch->buf_len)) { | ||
435 | /* try to get size */ | ||
436 | pkt_len = usbtouch->type->get_pkt_len( | ||
437 | usbtouch->buffer, usbtouch->buf_len); | ||
438 | |||
439 | /* drop? */ | ||
440 | if (unlikely(!pkt_len)) | ||
441 | goto out_flush_buf; | ||
442 | |||
443 | /* need to append -pkt_len bytes before able to get size */ | ||
444 | if (unlikely(pkt_len < 0)) { | ||
445 | int append = -pkt_len; | ||
446 | if (unlikely(append > len)) | ||
447 | append = len; | ||
448 | if (usbtouch->buf_len + append >= usbtouch->type->rept_size) | ||
449 | goto out_flush_buf; | ||
450 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); | ||
451 | usbtouch->buf_len += append; | ||
452 | |||
453 | pkt_len = usbtouch->type->get_pkt_len( | ||
454 | usbtouch->buffer, usbtouch->buf_len); | ||
455 | if (pkt_len < 0) | ||
456 | return; | ||
457 | } | ||
458 | |||
459 | /* append */ | ||
460 | tmp = pkt_len - usbtouch->buf_len; | ||
461 | if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) | ||
462 | goto out_flush_buf; | ||
463 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); | ||
464 | usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len); | ||
465 | |||
466 | buffer = pkt + tmp; | ||
467 | buf_len = len - tmp; | ||
468 | } else { | ||
469 | buffer = pkt; | ||
470 | buf_len = len; | ||
471 | } | ||
472 | |||
473 | /* loop over the received packet, process */ | ||
474 | pos = 0; | ||
475 | while (pos < buf_len) { | ||
476 | /* get packet len */ | ||
477 | pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len); | ||
478 | |||
479 | /* unknown packet: drop everything */ | ||
480 | if (unlikely(!pkt_len)) | ||
481 | goto out_flush_buf; | ||
482 | |||
483 | /* full packet: process */ | ||
484 | if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { | ||
485 | usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len); | ||
486 | } else { | ||
487 | /* incomplete packet: save in buffer */ | ||
488 | memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); | ||
489 | usbtouch->buf_len = buf_len - pos; | ||
490 | return; | ||
491 | } | ||
492 | pos += pkt_len; | ||
493 | } | ||
494 | |||
495 | out_flush_buf: | ||
496 | usbtouch->buf_len = 0; | ||
497 | return; | ||
498 | } | ||
499 | #endif | ||
500 | |||
501 | |||
380 | static void usbtouch_irq(struct urb *urb, struct pt_regs *regs) | 502 | static void usbtouch_irq(struct urb *urb, struct pt_regs *regs) |
381 | { | 503 | { |
382 | struct usbtouch_usb *usbtouch = urb->context; | 504 | struct usbtouch_usb *usbtouch = urb->context; |
@@ -386,7 +508,7 @@ static void usbtouch_irq(struct urb *urb, struct pt_regs *regs) | |||
386 | case 0: | 508 | case 0: |
387 | /* success */ | 509 | /* success */ |
388 | break; | 510 | break; |
389 | case -ETIMEDOUT: | 511 | case -ETIME: |
390 | /* this urb is timing out */ | 512 | /* this urb is timing out */ |
391 | dbg("%s - urb timed out - was the device unplugged?", | 513 | dbg("%s - urb timed out - was the device unplugged?", |
392 | __FUNCTION__); | 514 | __FUNCTION__); |
@@ -452,7 +574,7 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
452 | struct usb_endpoint_descriptor *endpoint; | 574 | struct usb_endpoint_descriptor *endpoint; |
453 | struct usb_device *udev = interface_to_usbdev(intf); | 575 | struct usb_device *udev = interface_to_usbdev(intf); |
454 | struct usbtouch_device_info *type; | 576 | struct usbtouch_device_info *type; |
455 | int err; | 577 | int err = -ENOMEM; |
456 | 578 | ||
457 | interface = intf->cur_altsetting; | 579 | interface = intf->cur_altsetting; |
458 | endpoint = &interface->endpoint[0].desc; | 580 | endpoint = &interface->endpoint[0].desc; |
@@ -526,6 +648,7 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
526 | usbtouch->data, type->rept_size, | 648 | usbtouch->data, type->rept_size, |
527 | usbtouch_irq, usbtouch, endpoint->bInterval); | 649 | usbtouch_irq, usbtouch, endpoint->bInterval); |
528 | 650 | ||
651 | usbtouch->irq->dev = usbtouch->udev; | ||
529 | usbtouch->irq->transfer_dma = usbtouch->data_dma; | 652 | usbtouch->irq->transfer_dma = usbtouch->data_dma; |
530 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 653 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
531 | 654 | ||
@@ -553,7 +676,7 @@ out_free_buffers: | |||
553 | out_free: | 676 | out_free: |
554 | input_free_device(input_dev); | 677 | input_free_device(input_dev); |
555 | kfree(usbtouch); | 678 | kfree(usbtouch); |
556 | return -ENOMEM; | 679 | return err; |
557 | } | 680 | } |
558 | 681 | ||
559 | static void usbtouch_disconnect(struct usb_interface *intf) | 682 | static void usbtouch_disconnect(struct usb_interface *intf) |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c deleted file mode 100644 index 369461a70b72..000000000000 --- a/drivers/usb/input/wacom.c +++ /dev/null | |||
@@ -1,1003 +0,0 @@ | |||
1 | /* | ||
2 | * USB Wacom Graphire and Wacom Intuos tablet support | ||
3 | * | ||
4 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> | ||
5 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> | ||
6 | * Copyright (c) 2000 Clifford Wolf <clifford@clifford.at> | ||
7 | * Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org> | ||
8 | * Copyright (c) 2000 James E. Blair <corvus@gnu.org> | ||
9 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | ||
10 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | ||
11 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | ||
12 | * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com> | ||
13 | * | ||
14 | * ChangeLog: | ||
15 | * v0.1 (vp) - Initial release | ||
16 | * v0.2 (aba) - Support for all buttons / combinations | ||
17 | * v0.3 (vp) - Support for Intuos added | ||
18 | * v0.4 (sm) - Support for more Intuos models, menustrip | ||
19 | * relative mode, proximity. | ||
20 | * v0.5 (vp) - Big cleanup, nifty features removed, | ||
21 | * they belong in userspace | ||
22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, | ||
23 | * use input_report_key instead of report_btn and | ||
24 | * other cleanups | ||
25 | * v1.11 (vp) - Add URB ->dev setting for new kernels | ||
26 | * v1.11 (jb) - Add support for the 4D Mouse & Lens | ||
27 | * v1.12 (de) - Add support for two more inking pen IDs | ||
28 | * v1.14 (vp) - Use new USB device id probing scheme. | ||
29 | * Fix Wacom Graphire mouse wheel | ||
30 | * v1.18 (vp) - Fix mouse wheel direction | ||
31 | * Make mouse relative | ||
32 | * v1.20 (fl) - Report tool id for Intuos devices | ||
33 | * - Multi tools support | ||
34 | * - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...) | ||
35 | * - Add PL models support | ||
36 | * - Fix Wacom Graphire mouse wheel again | ||
37 | * v1.21 (vp) - Removed protocol descriptions | ||
38 | * - Added MISC_SERIAL for tool serial numbers | ||
39 | * (gb) - Identify version on module load. | ||
40 | * v1.21.1 (fl) - added Graphire2 support | ||
41 | * v1.21.2 (fl) - added Intuos2 support | ||
42 | * - added all the PL ids | ||
43 | * v1.21.3 (fl) - added another eraser id from Neil Okamoto | ||
44 | * - added smooth filter for Graphire from Peri Hankey | ||
45 | * - added PenPartner support from Olaf van Es | ||
46 | * - new tool ids from Ole Martin Bjoerndalen | ||
47 | * v1.29 (pc) - Add support for more tablets | ||
48 | * - Fix pressure reporting | ||
49 | * v1.30 (vp) - Merge 2.4 and 2.5 drivers | ||
50 | * - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse | ||
51 | * - Cleanups here and there | ||
52 | * v1.30.1 (pi) - Added Graphire3 support | ||
53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... | ||
54 | * v1.43 (pc) - Added support for Cintiq 21UX | ||
55 | * - Fixed a Graphire bug | ||
56 | * - Merged wacom_intuos3_irq into wacom_intuos_irq | ||
57 | * v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc. | ||
58 | * - Report Device IDs | ||
59 | * v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19 | ||
60 | * - Minor data report fix | ||
61 | */ | ||
62 | |||
63 | /* | ||
64 | * This program is free software; you can redistribute it and/or modify | ||
65 | * it under the terms of the GNU General Public License as published by | ||
66 | * the Free Software Foundation; either version 2 of the License, or | ||
67 | * (at your option) any later version. | ||
68 | */ | ||
69 | |||
70 | #include <linux/kernel.h> | ||
71 | #include <linux/slab.h> | ||
72 | #include <linux/module.h> | ||
73 | #include <linux/init.h> | ||
74 | #include <linux/usb/input.h> | ||
75 | #include <asm/unaligned.h> | ||
76 | |||
77 | /* | ||
78 | * Version Information | ||
79 | */ | ||
80 | #define DRIVER_VERSION "v1.45" | ||
81 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
82 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | ||
83 | #define DRIVER_LICENSE "GPL" | ||
84 | |||
85 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
86 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
87 | MODULE_LICENSE(DRIVER_LICENSE); | ||
88 | |||
89 | #define USB_VENDOR_ID_WACOM 0x056a | ||
90 | #define STYLUS_DEVICE_ID 0x02 | ||
91 | #define CURSOR_DEVICE_ID 0x06 | ||
92 | #define ERASER_DEVICE_ID 0x0A | ||
93 | |||
94 | enum { | ||
95 | PENPARTNER = 0, | ||
96 | GRAPHIRE, | ||
97 | WACOM_G4, | ||
98 | PL, | ||
99 | INTUOS, | ||
100 | INTUOS3, | ||
101 | INTUOS312, | ||
102 | INTUOS319, | ||
103 | CINTIQ, | ||
104 | MAX_TYPE | ||
105 | }; | ||
106 | |||
107 | struct wacom_features { | ||
108 | char *name; | ||
109 | int pktlen; | ||
110 | int x_max; | ||
111 | int y_max; | ||
112 | int pressure_max; | ||
113 | int distance_max; | ||
114 | int type; | ||
115 | usb_complete_t irq; | ||
116 | }; | ||
117 | |||
118 | struct wacom { | ||
119 | signed char *data; | ||
120 | dma_addr_t data_dma; | ||
121 | struct input_dev *dev; | ||
122 | struct usb_device *usbdev; | ||
123 | struct urb *irq; | ||
124 | struct wacom_features *features; | ||
125 | int tool[2]; | ||
126 | int id[2]; | ||
127 | __u32 serial[2]; | ||
128 | char phys[32]; | ||
129 | }; | ||
130 | |||
131 | #define USB_REQ_GET_REPORT 0x01 | ||
132 | #define USB_REQ_SET_REPORT 0x09 | ||
133 | |||
134 | static int usb_get_report(struct usb_interface *intf, unsigned char type, | ||
135 | unsigned char id, void *buf, int size) | ||
136 | { | ||
137 | return usb_control_msg(interface_to_usbdev(intf), | ||
138 | usb_rcvctrlpipe(interface_to_usbdev(intf), 0), | ||
139 | USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
140 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
141 | buf, size, 100); | ||
142 | } | ||
143 | |||
144 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | ||
145 | unsigned char id, void *buf, int size) | ||
146 | { | ||
147 | return usb_control_msg(interface_to_usbdev(intf), | ||
148 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | ||
149 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
150 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
151 | buf, size, 1000); | ||
152 | } | ||
153 | |||
154 | static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | ||
155 | { | ||
156 | struct wacom *wacom = urb->context; | ||
157 | unsigned char *data = wacom->data; | ||
158 | struct input_dev *dev = wacom->dev; | ||
159 | int prox, pressure, id; | ||
160 | int retval; | ||
161 | |||
162 | switch (urb->status) { | ||
163 | case 0: | ||
164 | /* success */ | ||
165 | break; | ||
166 | case -ECONNRESET: | ||
167 | case -ENOENT: | ||
168 | case -ESHUTDOWN: | ||
169 | /* this urb is terminated, clean up */ | ||
170 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
171 | return; | ||
172 | default: | ||
173 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
174 | goto exit; | ||
175 | } | ||
176 | |||
177 | if (data[0] != 2) { | ||
178 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); | ||
179 | goto exit; | ||
180 | } | ||
181 | |||
182 | prox = data[1] & 0x40; | ||
183 | |||
184 | input_regs(dev, regs); | ||
185 | |||
186 | id = ERASER_DEVICE_ID; | ||
187 | if (prox) { | ||
188 | |||
189 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | ||
190 | if (wacom->features->pressure_max > 255) | ||
191 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); | ||
192 | pressure += (wacom->features->pressure_max + 1) / 2; | ||
193 | |||
194 | /* | ||
195 | * if going from out of proximity into proximity select between the eraser | ||
196 | * and the pen based on the state of the stylus2 button, choose eraser if | ||
197 | * pressed else choose pen. if not a proximity change from out to in, send | ||
198 | * an out of proximity for previous tool then a in for new tool. | ||
199 | */ | ||
200 | if (!wacom->tool[0]) { | ||
201 | /* Eraser bit set for DTF */ | ||
202 | if (data[1] & 0x10) | ||
203 | wacom->tool[1] = BTN_TOOL_RUBBER; | ||
204 | else | ||
205 | /* Going into proximity select tool */ | ||
206 | wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
207 | } else { | ||
208 | /* was entered with stylus2 pressed */ | ||
209 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { | ||
210 | /* report out proximity for previous tool */ | ||
211 | input_report_key(dev, wacom->tool[1], 0); | ||
212 | input_sync(dev); | ||
213 | wacom->tool[1] = BTN_TOOL_PEN; | ||
214 | goto exit; | ||
215 | } | ||
216 | } | ||
217 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
218 | /* Unknown tool selected default to pen tool */ | ||
219 | wacom->tool[1] = BTN_TOOL_PEN; | ||
220 | id = STYLUS_DEVICE_ID; | ||
221 | } | ||
222 | input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ | ||
223 | input_report_abs(dev, ABS_MISC, id); /* report tool id */ | ||
224 | input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); | ||
225 | input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); | ||
226 | input_report_abs(dev, ABS_PRESSURE, pressure); | ||
227 | |||
228 | input_report_key(dev, BTN_TOUCH, data[4] & 0x08); | ||
229 | input_report_key(dev, BTN_STYLUS, data[4] & 0x10); | ||
230 | /* Only allow the stylus2 button to be reported for the pen tool. */ | ||
231 | input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | ||
232 | } else { | ||
233 | /* report proximity-out of a (valid) tool */ | ||
234 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
235 | /* Unknown tool selected default to pen tool */ | ||
236 | wacom->tool[1] = BTN_TOOL_PEN; | ||
237 | } | ||
238 | input_report_key(dev, wacom->tool[1], prox); | ||
239 | } | ||
240 | |||
241 | wacom->tool[0] = prox; /* Save proximity state */ | ||
242 | input_sync(dev); | ||
243 | |||
244 | exit: | ||
245 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
246 | if (retval) | ||
247 | err ("%s - usb_submit_urb failed with result %d", | ||
248 | __FUNCTION__, retval); | ||
249 | } | ||
250 | |||
251 | static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) | ||
252 | { | ||
253 | struct wacom *wacom = urb->context; | ||
254 | unsigned char *data = wacom->data; | ||
255 | struct input_dev *dev = wacom->dev; | ||
256 | int retval, id; | ||
257 | |||
258 | switch (urb->status) { | ||
259 | case 0: | ||
260 | /* success */ | ||
261 | break; | ||
262 | case -ECONNRESET: | ||
263 | case -ENOENT: | ||
264 | case -ESHUTDOWN: | ||
265 | /* this urb is terminated, clean up */ | ||
266 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
267 | return; | ||
268 | default: | ||
269 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
270 | goto exit; | ||
271 | } | ||
272 | |||
273 | if (data[0] != 2) { | ||
274 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | ||
275 | goto exit; | ||
276 | } | ||
277 | |||
278 | input_regs(dev, regs); | ||
279 | if (data[1] & 0x04) { | ||
280 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); | ||
281 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); | ||
282 | id = ERASER_DEVICE_ID; | ||
283 | } else { | ||
284 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); | ||
285 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
286 | id = STYLUS_DEVICE_ID; | ||
287 | } | ||
288 | input_report_abs(dev, ABS_MISC, id); /* report tool id */ | ||
289 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2])); | ||
290 | input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4])); | ||
291 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | ||
292 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
293 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x10); | ||
294 | |||
295 | input_sync(dev); | ||
296 | |||
297 | exit: | ||
298 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
299 | if (retval) | ||
300 | err ("%s - usb_submit_urb failed with result %d", | ||
301 | __FUNCTION__, retval); | ||
302 | } | ||
303 | |||
304 | static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) | ||
305 | { | ||
306 | struct wacom *wacom = urb->context; | ||
307 | unsigned char *data = wacom->data; | ||
308 | struct input_dev *dev = wacom->dev; | ||
309 | int retval; | ||
310 | |||
311 | switch (urb->status) { | ||
312 | case 0: | ||
313 | /* success */ | ||
314 | break; | ||
315 | case -ECONNRESET: | ||
316 | case -ENOENT: | ||
317 | case -ESHUTDOWN: | ||
318 | /* this urb is terminated, clean up */ | ||
319 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
320 | return; | ||
321 | default: | ||
322 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
323 | goto exit; | ||
324 | } | ||
325 | |||
326 | if (data[0] != 2) { | ||
327 | printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | ||
328 | goto exit; | ||
329 | } | ||
330 | |||
331 | input_regs(dev, regs); | ||
332 | input_report_key(dev, BTN_TOOL_PEN, 1); | ||
333 | input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ | ||
334 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1])); | ||
335 | input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3])); | ||
336 | input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); | ||
337 | input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); | ||
338 | input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); | ||
339 | input_sync(dev); | ||
340 | |||
341 | exit: | ||
342 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
343 | if (retval) | ||
344 | err ("%s - usb_submit_urb failed with result %d", | ||
345 | __FUNCTION__, retval); | ||
346 | } | ||
347 | |||
348 | static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | ||
349 | { | ||
350 | struct wacom *wacom = urb->context; | ||
351 | unsigned char *data = wacom->data; | ||
352 | struct input_dev *dev = wacom->dev; | ||
353 | int x, y, id, rw; | ||
354 | int retval; | ||
355 | |||
356 | switch (urb->status) { | ||
357 | case 0: | ||
358 | /* success */ | ||
359 | break; | ||
360 | case -ECONNRESET: | ||
361 | case -ENOENT: | ||
362 | case -ESHUTDOWN: | ||
363 | /* this urb is terminated, clean up */ | ||
364 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
365 | return; | ||
366 | default: | ||
367 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
368 | goto exit; | ||
369 | } | ||
370 | |||
371 | if (data[0] == 99) return; /* for Volito tablets */ | ||
372 | |||
373 | if (data[0] != 2) { | ||
374 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | ||
375 | goto exit; | ||
376 | } | ||
377 | |||
378 | input_regs(dev, regs); | ||
379 | |||
380 | id = STYLUS_DEVICE_ID; | ||
381 | if (data[1] & 0x10) { /* in prox */ | ||
382 | |||
383 | switch ((data[1] >> 5) & 3) { | ||
384 | |||
385 | case 0: /* Pen */ | ||
386 | wacom->tool[0] = BTN_TOOL_PEN; | ||
387 | break; | ||
388 | |||
389 | case 1: /* Rubber */ | ||
390 | wacom->tool[0] = BTN_TOOL_RUBBER; | ||
391 | id = ERASER_DEVICE_ID; | ||
392 | break; | ||
393 | |||
394 | case 2: /* Mouse with wheel */ | ||
395 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | ||
396 | if (wacom->features->type == WACOM_G4) { | ||
397 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | ||
398 | input_report_rel(dev, REL_WHEEL, -rw); | ||
399 | } else | ||
400 | input_report_rel(dev, REL_WHEEL, -(signed char) data[6]); | ||
401 | /* fall through */ | ||
402 | |||
403 | case 3: /* Mouse without wheel */ | ||
404 | wacom->tool[0] = BTN_TOOL_MOUSE; | ||
405 | id = CURSOR_DEVICE_ID; | ||
406 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | ||
407 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | ||
408 | if (wacom->features->type == WACOM_G4) | ||
409 | input_report_abs(dev, ABS_DISTANCE, data[6]); | ||
410 | else | ||
411 | input_report_abs(dev, ABS_DISTANCE, data[7]); | ||
412 | break; | ||
413 | } | ||
414 | } | ||
415 | |||
416 | if (data[1] & 0x90) { | ||
417 | x = le16_to_cpu(*(__le16 *) &data[2]); | ||
418 | y = le16_to_cpu(*(__le16 *) &data[4]); | ||
419 | input_report_abs(dev, ABS_X, x); | ||
420 | input_report_abs(dev, ABS_Y, y); | ||
421 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { | ||
422 | input_report_abs(dev, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); | ||
423 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
424 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
425 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | if (data[1] & 0x10) | ||
430 | input_report_abs(dev, ABS_MISC, id); /* report tool id */ | ||
431 | else | ||
432 | input_report_abs(dev, ABS_MISC, 0); /* reset tool id */ | ||
433 | input_report_key(dev, wacom->tool[0], data[1] & 0x10); | ||
434 | input_sync(dev); | ||
435 | |||
436 | /* send pad data */ | ||
437 | if (wacom->features->type == WACOM_G4) { | ||
438 | if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) { | ||
439 | wacom->id[1] = 1; | ||
440 | wacom->serial[1] = (data[7] & 0xf8); | ||
441 | input_report_key(dev, BTN_0, (data[7] & 0x40)); | ||
442 | input_report_key(dev, BTN_4, (data[7] & 0x80)); | ||
443 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | ||
444 | input_report_rel(dev, REL_WHEEL, rw); | ||
445 | input_report_key(dev, BTN_TOOL_FINGER, 0xf0); | ||
446 | input_event(dev, EV_MSC, MSC_SERIAL, 0xf0); | ||
447 | } else if (wacom->id[1]) { | ||
448 | wacom->id[1] = 0; | ||
449 | input_report_key(dev, BTN_TOOL_FINGER, 0); | ||
450 | input_event(dev, EV_MSC, MSC_SERIAL, 0xf0); | ||
451 | } | ||
452 | input_sync(dev); | ||
453 | } | ||
454 | exit: | ||
455 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
456 | if (retval) | ||
457 | err ("%s - usb_submit_urb failed with result %d", | ||
458 | __FUNCTION__, retval); | ||
459 | } | ||
460 | |||
461 | static int wacom_intuos_inout(struct urb *urb) | ||
462 | { | ||
463 | struct wacom *wacom = urb->context; | ||
464 | unsigned char *data = wacom->data; | ||
465 | struct input_dev *dev = wacom->dev; | ||
466 | int idx; | ||
467 | |||
468 | /* tool number */ | ||
469 | idx = data[1] & 0x01; | ||
470 | |||
471 | /* Enter report */ | ||
472 | if ((data[1] & 0xfc) == 0xc0) { | ||
473 | /* serial number of the tool */ | ||
474 | wacom->serial[idx] = ((data[3] & 0x0f) << 28) + | ||
475 | (data[4] << 20) + (data[5] << 12) + | ||
476 | (data[6] << 4) + (data[7] >> 4); | ||
477 | |||
478 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); | ||
479 | switch (wacom->id[idx]) { | ||
480 | case 0x812: /* Inking pen */ | ||
481 | case 0x801: /* Intuos3 Inking pen */ | ||
482 | case 0x012: | ||
483 | wacom->tool[idx] = BTN_TOOL_PENCIL; | ||
484 | break; | ||
485 | case 0x822: /* Pen */ | ||
486 | case 0x842: | ||
487 | case 0x852: | ||
488 | case 0x823: /* Intuos3 Grip Pen */ | ||
489 | case 0x813: /* Intuos3 Classic Pen */ | ||
490 | case 0x885: /* Intuos3 Marker Pen */ | ||
491 | case 0x022: | ||
492 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
493 | break; | ||
494 | case 0x832: /* Stroke pen */ | ||
495 | case 0x032: | ||
496 | wacom->tool[idx] = BTN_TOOL_BRUSH; | ||
497 | break; | ||
498 | case 0x007: /* Mouse 4D and 2D */ | ||
499 | case 0x09c: | ||
500 | case 0x094: | ||
501 | case 0x017: /* Intuos3 2D Mouse */ | ||
502 | wacom->tool[idx] = BTN_TOOL_MOUSE; | ||
503 | break; | ||
504 | case 0x096: /* Lens cursor */ | ||
505 | case 0x097: /* Intuos3 Lens cursor */ | ||
506 | wacom->tool[idx] = BTN_TOOL_LENS; | ||
507 | break; | ||
508 | case 0x82a: /* Eraser */ | ||
509 | case 0x85a: | ||
510 | case 0x91a: | ||
511 | case 0xd1a: | ||
512 | case 0x0fa: | ||
513 | case 0x82b: /* Intuos3 Grip Pen Eraser */ | ||
514 | case 0x81b: /* Intuos3 Classic Pen Eraser */ | ||
515 | case 0x91b: /* Intuos3 Airbrush Eraser */ | ||
516 | wacom->tool[idx] = BTN_TOOL_RUBBER; | ||
517 | break; | ||
518 | case 0xd12: | ||
519 | case 0x912: | ||
520 | case 0x112: | ||
521 | case 0x913: /* Intuos3 Airbrush */ | ||
522 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | ||
523 | break; | ||
524 | default: /* Unknown tool */ | ||
525 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
526 | } | ||
527 | if(!((wacom->tool[idx] == BTN_TOOL_LENS) && | ||
528 | ((wacom->features->type == INTUOS312) | ||
529 | || (wacom->features->type == INTUOS319)))) { | ||
530 | input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */ | ||
531 | input_report_key(dev, wacom->tool[idx], 1); | ||
532 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
533 | input_sync(dev); | ||
534 | } | ||
535 | return 1; | ||
536 | } | ||
537 | |||
538 | /* Exit report */ | ||
539 | if ((data[1] & 0xfe) == 0x80) { | ||
540 | input_report_key(dev, wacom->tool[idx], 0); | ||
541 | input_report_abs(dev, ABS_MISC, 0); /* reset tool id */ | ||
542 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
543 | input_sync(dev); | ||
544 | return 1; | ||
545 | } | ||
546 | |||
547 | if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312) | ||
548 | || (wacom->features->type == INTUOS319))) | ||
549 | return 1; | ||
550 | else | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static void wacom_intuos_general(struct urb *urb) | ||
555 | { | ||
556 | struct wacom *wacom = urb->context; | ||
557 | unsigned char *data = wacom->data; | ||
558 | struct input_dev *dev = wacom->dev; | ||
559 | unsigned int t; | ||
560 | |||
561 | /* general pen packet */ | ||
562 | if ((data[1] & 0xb8) == 0xa0) { | ||
563 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
564 | input_report_abs(dev, ABS_PRESSURE, t); | ||
565 | input_report_abs(dev, ABS_TILT_X, | ||
566 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
567 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); | ||
568 | input_report_key(dev, BTN_STYLUS, data[1] & 2); | ||
569 | input_report_key(dev, BTN_STYLUS2, data[1] & 4); | ||
570 | input_report_key(dev, BTN_TOUCH, t > 10); | ||
571 | } | ||
572 | |||
573 | /* airbrush second packet */ | ||
574 | if ((data[1] & 0xbc) == 0xb4) { | ||
575 | input_report_abs(dev, ABS_WHEEL, | ||
576 | (data[6] << 2) | ((data[7] >> 6) & 3)); | ||
577 | input_report_abs(dev, ABS_TILT_X, | ||
578 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
579 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); | ||
580 | } | ||
581 | return; | ||
582 | } | ||
583 | |||
584 | static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | ||
585 | { | ||
586 | struct wacom *wacom = urb->context; | ||
587 | unsigned char *data = wacom->data; | ||
588 | struct input_dev *dev = wacom->dev; | ||
589 | unsigned int t; | ||
590 | int idx; | ||
591 | int retval; | ||
592 | |||
593 | switch (urb->status) { | ||
594 | case 0: | ||
595 | /* success */ | ||
596 | break; | ||
597 | case -ECONNRESET: | ||
598 | case -ENOENT: | ||
599 | case -ESHUTDOWN: | ||
600 | /* this urb is terminated, clean up */ | ||
601 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
602 | return; | ||
603 | default: | ||
604 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
605 | goto exit; | ||
606 | } | ||
607 | |||
608 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { | ||
609 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | ||
610 | goto exit; | ||
611 | } | ||
612 | |||
613 | input_regs(dev, regs); | ||
614 | |||
615 | /* tool number */ | ||
616 | idx = data[1] & 0x01; | ||
617 | |||
618 | /* pad packets. Works as a second tool and is always in prox */ | ||
619 | if (data[0] == 12) { | ||
620 | /* initiate the pad as a device */ | ||
621 | if (wacom->tool[1] != BTN_TOOL_FINGER) | ||
622 | wacom->tool[1] = BTN_TOOL_FINGER; | ||
623 | |||
624 | input_report_key(dev, BTN_0, (data[5] & 0x01)); | ||
625 | input_report_key(dev, BTN_1, (data[5] & 0x02)); | ||
626 | input_report_key(dev, BTN_2, (data[5] & 0x04)); | ||
627 | input_report_key(dev, BTN_3, (data[5] & 0x08)); | ||
628 | input_report_key(dev, BTN_4, (data[6] & 0x01)); | ||
629 | input_report_key(dev, BTN_5, (data[6] & 0x02)); | ||
630 | input_report_key(dev, BTN_6, (data[6] & 0x04)); | ||
631 | input_report_key(dev, BTN_7, (data[6] & 0x08)); | ||
632 | input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | ||
633 | input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | ||
634 | |||
635 | if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2]) | ||
636 | input_report_key(dev, wacom->tool[1], 1); | ||
637 | else | ||
638 | input_report_key(dev, wacom->tool[1], 0); | ||
639 | input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff); | ||
640 | input_sync(dev); | ||
641 | goto exit; | ||
642 | } | ||
643 | |||
644 | /* process in/out prox events */ | ||
645 | if (wacom_intuos_inout(urb)) | ||
646 | goto exit; | ||
647 | |||
648 | /* Cintiq doesn't send data when RDY bit isn't set */ | ||
649 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) | ||
650 | goto exit; | ||
651 | |||
652 | if (wacom->features->type >= INTUOS3) { | ||
653 | input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | ||
654 | input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | ||
655 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | ||
656 | } else { | ||
657 | input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); | ||
658 | input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); | ||
659 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); | ||
660 | } | ||
661 | |||
662 | /* process general packets */ | ||
663 | wacom_intuos_general(urb); | ||
664 | |||
665 | /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ | ||
666 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { | ||
667 | |||
668 | if (data[1] & 0x02) { | ||
669 | /* Rotation packet */ | ||
670 | if (wacom->features->type >= INTUOS3) { | ||
671 | /* I3 marker pen rotation reported as wheel | ||
672 | * due to valuator limitation | ||
673 | */ | ||
674 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
675 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | ||
676 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | ||
677 | input_report_abs(dev, ABS_WHEEL, t); | ||
678 | } else { | ||
679 | /* 4D mouse rotation packet */ | ||
680 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
681 | input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? | ||
682 | ((t - 1) / 2) : -t / 2); | ||
683 | } | ||
684 | |||
685 | } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) { | ||
686 | /* 4D mouse packet */ | ||
687 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
688 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
689 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
690 | |||
691 | input_report_key(dev, BTN_SIDE, data[8] & 0x20); | ||
692 | input_report_key(dev, BTN_EXTRA, data[8] & 0x10); | ||
693 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
694 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
695 | |||
696 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | ||
697 | /* 2D mouse packet */ | ||
698 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | ||
699 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | ||
700 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | ||
701 | input_report_rel(dev, REL_WHEEL, (data[8] & 0x01) | ||
702 | - ((data[8] & 0x02) >> 1)); | ||
703 | |||
704 | /* I3 2D mouse side buttons */ | ||
705 | if (wacom->features->type == INTUOS3) { | ||
706 | input_report_key(dev, BTN_SIDE, data[8] & 0x40); | ||
707 | input_report_key(dev, BTN_EXTRA, data[8] & 0x20); | ||
708 | } | ||
709 | |||
710 | } else if (wacom->features->type < INTUOS3) { | ||
711 | /* Lens cursor packets */ | ||
712 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
713 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
714 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
715 | input_report_key(dev, BTN_SIDE, data[8] & 0x10); | ||
716 | input_report_key(dev, BTN_EXTRA, data[8] & 0x08); | ||
717 | } | ||
718 | } | ||
719 | |||
720 | input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */ | ||
721 | input_report_key(dev, wacom->tool[idx], 1); | ||
722 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
723 | input_sync(dev); | ||
724 | |||
725 | exit: | ||
726 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
727 | if (retval) | ||
728 | err ("%s - usb_submit_urb failed with result %d", | ||
729 | __FUNCTION__, retval); | ||
730 | } | ||
731 | |||
732 | static struct wacom_features wacom_features[] = { | ||
733 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_penpartner_irq }, | ||
734 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
735 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
736 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
737 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
738 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
739 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq }, | ||
740 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq }, | ||
741 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
742 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | ||
743 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
744 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
745 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | ||
746 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
747 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
748 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
749 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
750 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
751 | { "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_pl_irq }, | ||
752 | { "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_pl_irq }, | ||
753 | { "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_pl_irq }, | ||
754 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq }, | ||
755 | { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq }, | ||
756 | { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq }, | ||
757 | { "Wacom PL700", 8, 6758, 5406, 511, 32, PL, wacom_pl_irq }, | ||
758 | { "Wacom PL510", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq }, | ||
759 | { "Wacom DTU710", 8, 34080, 27660, 511, 32, PL, wacom_pl_irq }, | ||
760 | { "Wacom DTF521", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq }, | ||
761 | { "Wacom DTF720", 8, 6858, 5506, 511, 32, PL, wacom_pl_irq }, | ||
762 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq }, | ||
763 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
764 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
765 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
766 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
767 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
768 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq }, | ||
769 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq }, | ||
770 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq }, | ||
771 | { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312, wacom_intuos_irq }, | ||
772 | { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319, wacom_intuos_irq }, | ||
773 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 15, INTUOS3, wacom_intuos_irq }, | ||
774 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq }, | ||
775 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, | ||
776 | { } | ||
777 | }; | ||
778 | |||
779 | static struct usb_device_id wacom_ids[] = { | ||
780 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, | ||
781 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, | ||
782 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, | ||
783 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, | ||
784 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, | ||
785 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, | ||
786 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, | ||
787 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, | ||
788 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | ||
789 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, | ||
790 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, | ||
791 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, | ||
792 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, | ||
793 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | ||
794 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | ||
795 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | ||
796 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, | ||
797 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, | ||
798 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, | ||
799 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, | ||
800 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, | ||
801 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, | ||
802 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, | ||
803 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, | ||
804 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | ||
805 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | ||
806 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | ||
807 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
808 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) }, | ||
809 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | ||
810 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | ||
811 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | ||
812 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, | ||
813 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, | ||
814 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, | ||
815 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | ||
816 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | ||
817 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | ||
818 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, | ||
819 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, | ||
820 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, | ||
821 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | ||
822 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | ||
823 | { } | ||
824 | }; | ||
825 | |||
826 | MODULE_DEVICE_TABLE(usb, wacom_ids); | ||
827 | |||
828 | static int wacom_open(struct input_dev *dev) | ||
829 | { | ||
830 | struct wacom *wacom = dev->private; | ||
831 | |||
832 | wacom->irq->dev = wacom->usbdev; | ||
833 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) | ||
834 | return -EIO; | ||
835 | |||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | static void wacom_close(struct input_dev *dev) | ||
840 | { | ||
841 | struct wacom *wacom = dev->private; | ||
842 | |||
843 | usb_kill_urb(wacom->irq); | ||
844 | } | ||
845 | |||
846 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
847 | { | ||
848 | struct usb_device *dev = interface_to_usbdev(intf); | ||
849 | struct usb_endpoint_descriptor *endpoint; | ||
850 | struct wacom *wacom; | ||
851 | struct input_dev *input_dev; | ||
852 | char rep_data[2], limit = 0; | ||
853 | |||
854 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | ||
855 | input_dev = input_allocate_device(); | ||
856 | if (!wacom || !input_dev) | ||
857 | goto fail1; | ||
858 | |||
859 | wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); | ||
860 | if (!wacom->data) | ||
861 | goto fail1; | ||
862 | |||
863 | wacom->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
864 | if (!wacom->irq) | ||
865 | goto fail2; | ||
866 | |||
867 | wacom->usbdev = dev; | ||
868 | wacom->dev = input_dev; | ||
869 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | ||
870 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | ||
871 | |||
872 | wacom->features = wacom_features + (id - wacom_ids); | ||
873 | if (wacom->features->pktlen > 10) | ||
874 | BUG(); | ||
875 | |||
876 | input_dev->name = wacom->features->name; | ||
877 | usb_to_input_id(dev, &input_dev->id); | ||
878 | |||
879 | input_dev->cdev.dev = &intf->dev; | ||
880 | input_dev->private = wacom; | ||
881 | input_dev->open = wacom_open; | ||
882 | input_dev->close = wacom_close; | ||
883 | |||
884 | input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); | ||
885 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); | ||
886 | input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0); | ||
887 | input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0); | ||
888 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); | ||
889 | input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC); | ||
890 | |||
891 | switch (wacom->features->type) { | ||
892 | case WACOM_G4: | ||
893 | input_dev->evbit[0] |= BIT(EV_MSC); | ||
894 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
895 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
896 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
897 | /* fall through */ | ||
898 | |||
899 | case GRAPHIRE: | ||
900 | input_dev->evbit[0] |= BIT(EV_REL); | ||
901 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
902 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
903 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | ||
904 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0); | ||
905 | break; | ||
906 | |||
907 | case INTUOS3: | ||
908 | case INTUOS312: | ||
909 | case INTUOS319: | ||
910 | case CINTIQ: | ||
911 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
912 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
913 | input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0); | ||
914 | input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0); | ||
915 | /* fall through */ | ||
916 | |||
917 | case INTUOS: | ||
918 | input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); | ||
919 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
920 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
921 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
922 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | ||
923 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | ||
924 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0); | ||
925 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | ||
926 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | ||
927 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | ||
928 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | ||
929 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | ||
930 | break; | ||
931 | |||
932 | case PL: | ||
933 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | ||
934 | break; | ||
935 | } | ||
936 | |||
937 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
938 | |||
939 | if (wacom->features->pktlen > 10) | ||
940 | BUG(); | ||
941 | |||
942 | usb_fill_int_urb(wacom->irq, dev, | ||
943 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
944 | wacom->data, wacom->features->pktlen, | ||
945 | wacom->features->irq, wacom, endpoint->bInterval); | ||
946 | wacom->irq->transfer_dma = wacom->data_dma; | ||
947 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
948 | |||
949 | input_register_device(wacom->dev); | ||
950 | |||
951 | /* Ask the tablet to report tablet data. Repeat until it succeeds */ | ||
952 | do { | ||
953 | rep_data[0] = 2; | ||
954 | rep_data[1] = 2; | ||
955 | usb_set_report(intf, 3, 2, rep_data, 2); | ||
956 | usb_get_report(intf, 3, 2, rep_data, 2); | ||
957 | } while (rep_data[1] != 2 && limit++ < 5); | ||
958 | |||
959 | usb_set_intfdata(intf, wacom); | ||
960 | return 0; | ||
961 | |||
962 | fail2: usb_buffer_free(dev, 10, wacom->data, wacom->data_dma); | ||
963 | fail1: input_free_device(input_dev); | ||
964 | kfree(wacom); | ||
965 | return -ENOMEM; | ||
966 | } | ||
967 | |||
968 | static void wacom_disconnect(struct usb_interface *intf) | ||
969 | { | ||
970 | struct wacom *wacom = usb_get_intfdata (intf); | ||
971 | |||
972 | usb_set_intfdata(intf, NULL); | ||
973 | if (wacom) { | ||
974 | usb_kill_urb(wacom->irq); | ||
975 | input_unregister_device(wacom->dev); | ||
976 | usb_free_urb(wacom->irq); | ||
977 | usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma); | ||
978 | kfree(wacom); | ||
979 | } | ||
980 | } | ||
981 | |||
982 | static struct usb_driver wacom_driver = { | ||
983 | .name = "wacom", | ||
984 | .probe = wacom_probe, | ||
985 | .disconnect = wacom_disconnect, | ||
986 | .id_table = wacom_ids, | ||
987 | }; | ||
988 | |||
989 | static int __init wacom_init(void) | ||
990 | { | ||
991 | int result = usb_register(&wacom_driver); | ||
992 | if (result == 0) | ||
993 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
994 | return result; | ||
995 | } | ||
996 | |||
997 | static void __exit wacom_exit(void) | ||
998 | { | ||
999 | usb_deregister(&wacom_driver); | ||
1000 | } | ||
1001 | |||
1002 | module_init(wacom_init); | ||
1003 | module_exit(wacom_exit); | ||
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h new file mode 100644 index 000000000000..832737b658cf --- /dev/null +++ b/drivers/usb/input/wacom.h | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/wacom.h | ||
3 | * | ||
4 | * USB Wacom Graphire and Wacom Intuos tablet support | ||
5 | * | ||
6 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> | ||
7 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> | ||
8 | * Copyright (c) 2000 Clifford Wolf <clifford@clifford.at> | ||
9 | * Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org> | ||
10 | * Copyright (c) 2000 James E. Blair <corvus@gnu.org> | ||
11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | ||
12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | ||
13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | ||
14 | * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com> | ||
15 | * | ||
16 | * ChangeLog: | ||
17 | * v0.1 (vp) - Initial release | ||
18 | * v0.2 (aba) - Support for all buttons / combinations | ||
19 | * v0.3 (vp) - Support for Intuos added | ||
20 | * v0.4 (sm) - Support for more Intuos models, menustrip | ||
21 | * relative mode, proximity. | ||
22 | * v0.5 (vp) - Big cleanup, nifty features removed, | ||
23 | * they belong in userspace | ||
24 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, | ||
25 | * use input_report_key instead of report_btn and | ||
26 | * other cleanups | ||
27 | * v1.11 (vp) - Add URB ->dev setting for new kernels | ||
28 | * v1.11 (jb) - Add support for the 4D Mouse & Lens | ||
29 | * v1.12 (de) - Add support for two more inking pen IDs | ||
30 | * v1.14 (vp) - Use new USB device id probing scheme. | ||
31 | * Fix Wacom Graphire mouse wheel | ||
32 | * v1.18 (vp) - Fix mouse wheel direction | ||
33 | * Make mouse relative | ||
34 | * v1.20 (fl) - Report tool id for Intuos devices | ||
35 | * - Multi tools support | ||
36 | * - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...) | ||
37 | * - Add PL models support | ||
38 | * - Fix Wacom Graphire mouse wheel again | ||
39 | * v1.21 (vp) - Removed protocol descriptions | ||
40 | * - Added MISC_SERIAL for tool serial numbers | ||
41 | * (gb) - Identify version on module load. | ||
42 | * v1.21.1 (fl) - added Graphire2 support | ||
43 | * v1.21.2 (fl) - added Intuos2 support | ||
44 | * - added all the PL ids | ||
45 | * v1.21.3 (fl) - added another eraser id from Neil Okamoto | ||
46 | * - added smooth filter for Graphire from Peri Hankey | ||
47 | * - added PenPartner support from Olaf van Es | ||
48 | * - new tool ids from Ole Martin Bjoerndalen | ||
49 | * v1.29 (pc) - Add support for more tablets | ||
50 | * - Fix pressure reporting | ||
51 | * v1.30 (vp) - Merge 2.4 and 2.5 drivers | ||
52 | * - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse | ||
53 | * - Cleanups here and there | ||
54 | * v1.30.1 (pi) - Added Graphire3 support | ||
55 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... | ||
56 | * v1.43 (pc) - Added support for Cintiq 21UX | ||
57 | * - Fixed a Graphire bug | ||
58 | * - Merged wacom_intuos3_irq into wacom_intuos_irq | ||
59 | * v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc. | ||
60 | * - Report Device IDs | ||
61 | * v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19 | ||
62 | * - Minor data report fix | ||
63 | * v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c, | ||
64 | * - where wacom_sys.c deals with system specific code, | ||
65 | * - and wacom_wac.c deals with Wacom specific code | ||
66 | */ | ||
67 | |||
68 | /* | ||
69 | * This program is free software; you can redistribute it and/or modify | ||
70 | * it under the terms of the GNU General Public License as published by | ||
71 | * the Free Software Foundation; either version 2 of the License, or | ||
72 | * (at your option) any later version. | ||
73 | */ | ||
74 | #ifndef WACOM_H | ||
75 | #define WACOM_H | ||
76 | #include <linux/kernel.h> | ||
77 | #include <linux/slab.h> | ||
78 | #include <linux/module.h> | ||
79 | #include <linux/init.h> | ||
80 | #include <linux/usb/input.h> | ||
81 | #include <asm/unaligned.h> | ||
82 | |||
83 | /* | ||
84 | * Version Information | ||
85 | */ | ||
86 | #define DRIVER_VERSION "v1.46" | ||
87 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
88 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | ||
89 | #define DRIVER_LICENSE "GPL" | ||
90 | |||
91 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
92 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
93 | MODULE_LICENSE(DRIVER_LICENSE); | ||
94 | |||
95 | #define USB_VENDOR_ID_WACOM 0x056a | ||
96 | |||
97 | struct wacom { | ||
98 | dma_addr_t data_dma; | ||
99 | struct input_dev *dev; | ||
100 | struct usb_device *usbdev; | ||
101 | struct urb *irq; | ||
102 | struct wacom_wac * wacom_wac; | ||
103 | char phys[32]; | ||
104 | }; | ||
105 | |||
106 | struct wacom_combo { | ||
107 | struct wacom * wacom; | ||
108 | struct urb * urb; | ||
109 | struct pt_regs *regs; | ||
110 | }; | ||
111 | |||
112 | extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); | ||
113 | extern void wacom_sys_irq(struct urb *urb, struct pt_regs *regs); | ||
114 | extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); | ||
115 | extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); | ||
116 | extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); | ||
117 | extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value); | ||
118 | extern void wacom_input_regs(void *wcombo); | ||
119 | extern void wacom_input_sync(void *wcombo); | ||
120 | extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
121 | extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
122 | extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
123 | extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
124 | extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
125 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
126 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
127 | extern __u16 wacom_le16_to_cpu(unsigned char *data); | ||
128 | extern __u16 wacom_be16_to_cpu(unsigned char *data); | ||
129 | extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id); | ||
130 | extern const struct usb_device_id * get_device_table(void); | ||
131 | |||
132 | #endif | ||
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c new file mode 100644 index 000000000000..7c3b52bdd9d6 --- /dev/null +++ b/drivers/usb/input/wacom_sys.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/wacom_sys.c | ||
3 | * | ||
4 | * USB Wacom Graphire and Wacom Intuos tablet support - system specific code | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include "wacom.h" | ||
15 | #include "wacom_wac.h" | ||
16 | |||
17 | #define USB_REQ_GET_REPORT 0x01 | ||
18 | #define USB_REQ_SET_REPORT 0x09 | ||
19 | |||
20 | static int usb_get_report(struct usb_interface *intf, unsigned char type, | ||
21 | unsigned char id, void *buf, int size) | ||
22 | { | ||
23 | return usb_control_msg(interface_to_usbdev(intf), | ||
24 | usb_rcvctrlpipe(interface_to_usbdev(intf), 0), | ||
25 | USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
26 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
27 | buf, size, 100); | ||
28 | } | ||
29 | |||
30 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | ||
31 | unsigned char id, void *buf, int size) | ||
32 | { | ||
33 | return usb_control_msg(interface_to_usbdev(intf), | ||
34 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | ||
35 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
36 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | ||
37 | buf, size, 1000); | ||
38 | } | ||
39 | |||
40 | static struct input_dev * get_input_dev(struct wacom_combo *wcombo) | ||
41 | { | ||
42 | return wcombo->wacom->dev; | ||
43 | } | ||
44 | |||
45 | void wacom_sys_irq(struct urb *urb, struct pt_regs *regs) | ||
46 | { | ||
47 | struct wacom *wacom = urb->context; | ||
48 | struct wacom_combo wcombo; | ||
49 | int retval; | ||
50 | |||
51 | switch (urb->status) { | ||
52 | case 0: | ||
53 | /* success */ | ||
54 | break; | ||
55 | case -ECONNRESET: | ||
56 | case -ENOENT: | ||
57 | case -ESHUTDOWN: | ||
58 | /* this urb is terminated, clean up */ | ||
59 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
60 | return; | ||
61 | default: | ||
62 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
63 | goto exit; | ||
64 | } | ||
65 | |||
66 | wcombo.wacom = wacom; | ||
67 | wcombo.urb = urb; | ||
68 | wcombo.regs = regs; | ||
69 | |||
70 | if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo)) | ||
71 | input_sync(get_input_dev(&wcombo)); | ||
72 | |||
73 | exit: | ||
74 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
75 | if (retval) | ||
76 | err ("%s - usb_submit_urb failed with result %d", | ||
77 | __FUNCTION__, retval); | ||
78 | } | ||
79 | |||
80 | void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) | ||
81 | { | ||
82 | input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data); | ||
83 | return; | ||
84 | } | ||
85 | |||
86 | void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data) | ||
87 | { | ||
88 | input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data); | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data) | ||
93 | { | ||
94 | input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data); | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value) | ||
99 | { | ||
100 | input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | __u16 wacom_be16_to_cpu(unsigned char *data) | ||
105 | { | ||
106 | __u16 value; | ||
107 | value = be16_to_cpu(*(__be16 *) data); | ||
108 | return value; | ||
109 | } | ||
110 | |||
111 | __u16 wacom_le16_to_cpu(unsigned char *data) | ||
112 | { | ||
113 | __u16 value; | ||
114 | value = be16_to_cpu(*(__be16 *) data); | ||
115 | return value; | ||
116 | } | ||
117 | |||
118 | void wacom_input_regs(void *wcombo) | ||
119 | { | ||
120 | input_regs(get_input_dev((struct wacom_combo *)wcombo), ((struct wacom_combo *)wcombo)->regs); | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | void wacom_input_sync(void *wcombo) | ||
125 | { | ||
126 | input_sync(get_input_dev((struct wacom_combo *)wcombo)); | ||
127 | return; | ||
128 | } | ||
129 | |||
130 | static int wacom_open(struct input_dev *dev) | ||
131 | { | ||
132 | struct wacom *wacom = dev->private; | ||
133 | |||
134 | wacom->irq->dev = wacom->usbdev; | ||
135 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) | ||
136 | return -EIO; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static void wacom_close(struct input_dev *dev) | ||
142 | { | ||
143 | struct wacom *wacom = dev->private; | ||
144 | |||
145 | usb_kill_urb(wacom->irq); | ||
146 | } | ||
147 | |||
148 | void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
149 | { | ||
150 | input_dev->evbit[0] |= BIT(EV_MSC); | ||
151 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
152 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
153 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
154 | } | ||
155 | |||
156 | void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
157 | { | ||
158 | input_dev->evbit[0] |= BIT(EV_REL); | ||
159 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
160 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
161 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | ||
162 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | ||
163 | } | ||
164 | |||
165 | void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
166 | { | ||
167 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
168 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
169 | input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0); | ||
170 | input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0); | ||
171 | } | ||
172 | |||
173 | void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
174 | { | ||
175 | input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); | ||
176 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
177 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
178 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
179 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | ||
180 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | ||
181 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | ||
182 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | ||
183 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | ||
184 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | ||
185 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | ||
186 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | ||
187 | } | ||
188 | |||
189 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
190 | { | ||
191 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | ||
192 | } | ||
193 | |||
194 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
195 | { | ||
196 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER); | ||
197 | } | ||
198 | |||
199 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
200 | { | ||
201 | struct usb_device *dev = interface_to_usbdev(intf); | ||
202 | struct usb_endpoint_descriptor *endpoint; | ||
203 | struct wacom *wacom; | ||
204 | struct wacom_wac *wacom_wac; | ||
205 | struct input_dev *input_dev; | ||
206 | char rep_data[2], limit = 0; | ||
207 | |||
208 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | ||
209 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); | ||
210 | input_dev = input_allocate_device(); | ||
211 | if (!wacom || !input_dev || !wacom_wac) | ||
212 | goto fail1; | ||
213 | |||
214 | wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); | ||
215 | if (!wacom_wac->data) | ||
216 | goto fail1; | ||
217 | |||
218 | wacom->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
219 | if (!wacom->irq) | ||
220 | goto fail2; | ||
221 | |||
222 | wacom->usbdev = dev; | ||
223 | wacom->dev = input_dev; | ||
224 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | ||
225 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | ||
226 | |||
227 | wacom_wac->features = get_wacom_feature(id); | ||
228 | if (wacom_wac->features->pktlen > 10) | ||
229 | BUG(); | ||
230 | |||
231 | input_dev->name = wacom_wac->features->name; | ||
232 | wacom->wacom_wac = wacom_wac; | ||
233 | usb_to_input_id(dev, &input_dev->id); | ||
234 | |||
235 | input_dev->cdev.dev = &intf->dev; | ||
236 | input_dev->private = wacom; | ||
237 | input_dev->open = wacom_open; | ||
238 | input_dev->close = wacom_close; | ||
239 | |||
240 | input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); | ||
241 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); | ||
242 | input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0); | ||
243 | input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); | ||
244 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); | ||
245 | input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC); | ||
246 | |||
247 | wacom_init_input_dev(input_dev, wacom_wac); | ||
248 | |||
249 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | ||
250 | |||
251 | usb_fill_int_urb(wacom->irq, dev, | ||
252 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | ||
253 | wacom_wac->data, wacom_wac->features->pktlen, | ||
254 | wacom_wac->features->irq, wacom, endpoint->bInterval); | ||
255 | wacom->irq->transfer_dma = wacom->data_dma; | ||
256 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
257 | |||
258 | input_register_device(wacom->dev); | ||
259 | |||
260 | /* Ask the tablet to report tablet data. Repeat until it succeeds */ | ||
261 | do { | ||
262 | rep_data[0] = 2; | ||
263 | rep_data[1] = 2; | ||
264 | usb_set_report(intf, 3, 2, rep_data, 2); | ||
265 | usb_get_report(intf, 3, 2, rep_data, 2); | ||
266 | } while (rep_data[1] != 2 && limit++ < 5); | ||
267 | |||
268 | usb_set_intfdata(intf, wacom); | ||
269 | return 0; | ||
270 | |||
271 | fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); | ||
272 | fail1: input_free_device(input_dev); | ||
273 | kfree(wacom); | ||
274 | kfree(wacom_wac); | ||
275 | return -ENOMEM; | ||
276 | } | ||
277 | |||
278 | static void wacom_disconnect(struct usb_interface *intf) | ||
279 | { | ||
280 | struct wacom *wacom = usb_get_intfdata (intf); | ||
281 | |||
282 | usb_set_intfdata(intf, NULL); | ||
283 | if (wacom) { | ||
284 | usb_kill_urb(wacom->irq); | ||
285 | input_unregister_device(wacom->dev); | ||
286 | usb_free_urb(wacom->irq); | ||
287 | usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); | ||
288 | kfree(wacom); | ||
289 | kfree(wacom->wacom_wac); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | static struct usb_driver wacom_driver = { | ||
294 | .name = "wacom", | ||
295 | .probe = wacom_probe, | ||
296 | .disconnect = wacom_disconnect, | ||
297 | }; | ||
298 | |||
299 | static int __init wacom_init(void) | ||
300 | { | ||
301 | int result; | ||
302 | wacom_driver.id_table = get_device_table(); | ||
303 | result = usb_register(&wacom_driver); | ||
304 | if (result == 0) | ||
305 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
306 | return result; | ||
307 | } | ||
308 | |||
309 | static void __exit wacom_exit(void) | ||
310 | { | ||
311 | usb_deregister(&wacom_driver); | ||
312 | } | ||
313 | |||
314 | module_init(wacom_init); | ||
315 | module_exit(wacom_exit); | ||
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c new file mode 100644 index 000000000000..85d458c98b6e --- /dev/null +++ b/drivers/usb/input/wacom_wac.c | |||
@@ -0,0 +1,646 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/wacom_wac.c | ||
3 | * | ||
4 | * USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | #include "wacom.h" | ||
15 | #include "wacom_wac.h" | ||
16 | |||
17 | static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) | ||
18 | { | ||
19 | unsigned char *data = wacom->data; | ||
20 | |||
21 | switch (data[0]) { | ||
22 | case 1: | ||
23 | wacom_input_regs(wcombo); | ||
24 | if (data[5] & 0x80) { | ||
25 | wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
26 | wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; | ||
27 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
28 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | ||
29 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
30 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
31 | wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | ||
32 | wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); | ||
33 | wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | ||
34 | } else { | ||
35 | wacom_report_key(wcombo, wacom->tool[0], 0); | ||
36 | wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ | ||
37 | wacom_report_abs(wcombo, ABS_PRESSURE, -1); | ||
38 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
39 | } | ||
40 | break; | ||
41 | case 2: | ||
42 | wacom_input_regs(wcombo); | ||
43 | wacom_report_key(wcombo, BTN_TOOL_PEN, 1); | ||
44 | wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ | ||
45 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
46 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
47 | wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | ||
48 | wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); | ||
49 | wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | ||
50 | break; | ||
51 | default: | ||
52 | printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | ||
53 | return 0; | ||
54 | } | ||
55 | return 1; | ||
56 | } | ||
57 | |||
58 | static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | ||
59 | { | ||
60 | unsigned char *data = wacom->data; | ||
61 | int prox, id, pressure; | ||
62 | |||
63 | if (data[0] != 2) { | ||
64 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | prox = data[1] & 0x40; | ||
69 | |||
70 | wacom_input_regs(wcombo); | ||
71 | |||
72 | id = ERASER_DEVICE_ID; | ||
73 | if (prox) { | ||
74 | |||
75 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | ||
76 | if (wacom->features->pressure_max > 255) | ||
77 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); | ||
78 | pressure += (wacom->features->pressure_max + 1) / 2; | ||
79 | |||
80 | /* | ||
81 | * if going from out of proximity into proximity select between the eraser | ||
82 | * and the pen based on the state of the stylus2 button, choose eraser if | ||
83 | * pressed else choose pen. if not a proximity change from out to in, send | ||
84 | * an out of proximity for previous tool then a in for new tool. | ||
85 | */ | ||
86 | if (!wacom->tool[0]) { | ||
87 | /* Eraser bit set for DTF */ | ||
88 | if (data[1] & 0x10) | ||
89 | wacom->tool[1] = BTN_TOOL_RUBBER; | ||
90 | else | ||
91 | /* Going into proximity select tool */ | ||
92 | wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
93 | } else { | ||
94 | /* was entered with stylus2 pressed */ | ||
95 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { | ||
96 | /* report out proximity for previous tool */ | ||
97 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
98 | wacom_input_sync(wcombo); | ||
99 | wacom->tool[1] = BTN_TOOL_PEN; | ||
100 | return 0; | ||
101 | } | ||
102 | } | ||
103 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
104 | /* Unknown tool selected default to pen tool */ | ||
105 | wacom->tool[1] = BTN_TOOL_PEN; | ||
106 | id = STYLUS_DEVICE_ID; | ||
107 | } | ||
108 | wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */ | ||
109 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ | ||
110 | wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); | ||
111 | wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); | ||
112 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | ||
113 | |||
114 | wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08); | ||
115 | wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10); | ||
116 | /* Only allow the stylus2 button to be reported for the pen tool. */ | ||
117 | wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | ||
118 | } else { | ||
119 | /* report proximity-out of a (valid) tool */ | ||
120 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
121 | /* Unknown tool selected default to pen tool */ | ||
122 | wacom->tool[1] = BTN_TOOL_PEN; | ||
123 | } | ||
124 | wacom_report_key(wcombo, wacom->tool[1], prox); | ||
125 | } | ||
126 | |||
127 | wacom->tool[0] = prox; /* Save proximity state */ | ||
128 | return 1; | ||
129 | } | ||
130 | |||
131 | static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | ||
132 | { | ||
133 | unsigned char *data = wacom->data; | ||
134 | int id; | ||
135 | |||
136 | if (data[0] != 2) { | ||
137 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | wacom_input_regs(wcombo); | ||
142 | if (data[1] & 0x04) { | ||
143 | wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20); | ||
144 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08); | ||
145 | id = ERASER_DEVICE_ID; | ||
146 | } else { | ||
147 | wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20); | ||
148 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | ||
149 | id = STYLUS_DEVICE_ID; | ||
150 | } | ||
151 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ | ||
152 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
153 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
154 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
155 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | ||
156 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | ||
157 | return 1; | ||
158 | } | ||
159 | |||
160 | static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | ||
161 | { | ||
162 | unsigned char *data = wacom->data; | ||
163 | int x, y, id, rw; | ||
164 | |||
165 | if (data[0] != 2) { | ||
166 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | wacom_input_regs(wcombo); | ||
171 | |||
172 | id = STYLUS_DEVICE_ID; | ||
173 | if (data[1] & 0x10) { /* in prox */ | ||
174 | |||
175 | switch ((data[1] >> 5) & 3) { | ||
176 | |||
177 | case 0: /* Pen */ | ||
178 | wacom->tool[0] = BTN_TOOL_PEN; | ||
179 | break; | ||
180 | |||
181 | case 1: /* Rubber */ | ||
182 | wacom->tool[0] = BTN_TOOL_RUBBER; | ||
183 | id = ERASER_DEVICE_ID; | ||
184 | break; | ||
185 | |||
186 | case 2: /* Mouse with wheel */ | ||
187 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); | ||
188 | if (wacom->features->type == WACOM_G4) { | ||
189 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | ||
190 | wacom_report_rel(wcombo, REL_WHEEL, -rw); | ||
191 | } else | ||
192 | wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); | ||
193 | /* fall through */ | ||
194 | |||
195 | case 3: /* Mouse without wheel */ | ||
196 | wacom->tool[0] = BTN_TOOL_MOUSE; | ||
197 | id = CURSOR_DEVICE_ID; | ||
198 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | ||
199 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | ||
200 | if (wacom->features->type == WACOM_G4) | ||
201 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6]); | ||
202 | else | ||
203 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7]); | ||
204 | break; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | if (data[1] & 0x90) { | ||
209 | x = wacom_le16_to_cpu(&data[2]); | ||
210 | y = wacom_le16_to_cpu(&data[4]); | ||
211 | wacom_report_abs(wcombo, ABS_X, x); | ||
212 | wacom_report_abs(wcombo, ABS_Y, y); | ||
213 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { | ||
214 | wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); | ||
215 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | ||
216 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | ||
217 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | if (data[1] & 0x10) | ||
222 | wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ | ||
223 | else | ||
224 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
225 | wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10); | ||
226 | wacom_input_sync(wcombo); | ||
227 | |||
228 | /* send pad data */ | ||
229 | if (wacom->features->type == WACOM_G4) { | ||
230 | if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) { | ||
231 | wacom->id[1] = 1; | ||
232 | wacom->serial[1] = (data[7] & 0xf8); | ||
233 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | ||
234 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | ||
235 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | ||
236 | wacom_report_rel(wcombo, REL_WHEEL, rw); | ||
237 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | ||
238 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
239 | } else if (wacom->id[1]) { | ||
240 | wacom->id[1] = 0; | ||
241 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
242 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
243 | } | ||
244 | } | ||
245 | return 1; | ||
246 | } | ||
247 | |||
248 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | ||
249 | { | ||
250 | unsigned char *data = wacom->data; | ||
251 | int idx; | ||
252 | |||
253 | /* tool number */ | ||
254 | idx = data[1] & 0x01; | ||
255 | |||
256 | /* Enter report */ | ||
257 | if ((data[1] & 0xfc) == 0xc0) { | ||
258 | /* serial number of the tool */ | ||
259 | wacom->serial[idx] = ((data[3] & 0x0f) << 28) + | ||
260 | (data[4] << 20) + (data[5] << 12) + | ||
261 | (data[6] << 4) + (data[7] >> 4); | ||
262 | |||
263 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); | ||
264 | switch (wacom->id[idx]) { | ||
265 | case 0x812: /* Inking pen */ | ||
266 | case 0x801: /* Intuos3 Inking pen */ | ||
267 | case 0x012: | ||
268 | wacom->tool[idx] = BTN_TOOL_PENCIL; | ||
269 | break; | ||
270 | case 0x822: /* Pen */ | ||
271 | case 0x842: | ||
272 | case 0x852: | ||
273 | case 0x823: /* Intuos3 Grip Pen */ | ||
274 | case 0x813: /* Intuos3 Classic Pen */ | ||
275 | case 0x885: /* Intuos3 Marker Pen */ | ||
276 | case 0x022: | ||
277 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
278 | break; | ||
279 | case 0x832: /* Stroke pen */ | ||
280 | case 0x032: | ||
281 | wacom->tool[idx] = BTN_TOOL_BRUSH; | ||
282 | break; | ||
283 | case 0x007: /* Mouse 4D and 2D */ | ||
284 | case 0x09c: | ||
285 | case 0x094: | ||
286 | case 0x017: /* Intuos3 2D Mouse */ | ||
287 | wacom->tool[idx] = BTN_TOOL_MOUSE; | ||
288 | break; | ||
289 | case 0x096: /* Lens cursor */ | ||
290 | case 0x097: /* Intuos3 Lens cursor */ | ||
291 | wacom->tool[idx] = BTN_TOOL_LENS; | ||
292 | break; | ||
293 | case 0x82a: /* Eraser */ | ||
294 | case 0x85a: | ||
295 | case 0x91a: | ||
296 | case 0xd1a: | ||
297 | case 0x0fa: | ||
298 | case 0x82b: /* Intuos3 Grip Pen Eraser */ | ||
299 | case 0x81b: /* Intuos3 Classic Pen Eraser */ | ||
300 | case 0x91b: /* Intuos3 Airbrush Eraser */ | ||
301 | wacom->tool[idx] = BTN_TOOL_RUBBER; | ||
302 | break; | ||
303 | case 0xd12: | ||
304 | case 0x912: | ||
305 | case 0x112: | ||
306 | case 0x913: /* Intuos3 Airbrush */ | ||
307 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | ||
308 | break; | ||
309 | default: /* Unknown tool */ | ||
310 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
311 | } | ||
312 | /* only large I3 support Lens Cursor */ | ||
313 | if(!((wacom->tool[idx] == BTN_TOOL_LENS) && | ||
314 | (wacom->features->type == INTUOS3))) { | ||
315 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ | ||
316 | wacom_report_key(wcombo, wacom->tool[idx], 1); | ||
317 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
318 | return 2; | ||
319 | } | ||
320 | return 1; | ||
321 | } | ||
322 | |||
323 | /* Exit report */ | ||
324 | if ((data[1] & 0xfe) == 0x80) { | ||
325 | wacom_report_key(wcombo, wacom->tool[idx], 0); | ||
326 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | ||
327 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
328 | return 2; | ||
329 | } | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | ||
334 | { | ||
335 | unsigned char *data = wacom->data; | ||
336 | unsigned int t; | ||
337 | |||
338 | /* general pen packet */ | ||
339 | if ((data[1] & 0xb8) == 0xa0) { | ||
340 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
341 | wacom_report_abs(wcombo, ABS_PRESSURE, t); | ||
342 | wacom_report_abs(wcombo, ABS_TILT_X, | ||
343 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
344 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | ||
345 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2); | ||
346 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4); | ||
347 | wacom_report_key(wcombo, BTN_TOUCH, t > 10); | ||
348 | } | ||
349 | |||
350 | /* airbrush second packet */ | ||
351 | if ((data[1] & 0xbc) == 0xb4) { | ||
352 | wacom_report_abs(wcombo, ABS_WHEEL, | ||
353 | (data[6] << 2) | ((data[7] >> 6) & 3)); | ||
354 | wacom_report_abs(wcombo, ABS_TILT_X, | ||
355 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | ||
356 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | ||
357 | } | ||
358 | return; | ||
359 | } | ||
360 | |||
361 | static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | ||
362 | { | ||
363 | unsigned char *data = wacom->data; | ||
364 | unsigned int t; | ||
365 | int idx, result; | ||
366 | |||
367 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { | ||
368 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | wacom_input_regs(wcombo); | ||
373 | |||
374 | /* tool number */ | ||
375 | idx = data[1] & 0x01; | ||
376 | |||
377 | /* pad packets. Works as a second tool and is always in prox */ | ||
378 | if (data[0] == 12) { | ||
379 | /* initiate the pad as a device */ | ||
380 | if (wacom->tool[1] != BTN_TOOL_FINGER) | ||
381 | wacom->tool[1] = BTN_TOOL_FINGER; | ||
382 | |||
383 | wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); | ||
384 | wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); | ||
385 | wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); | ||
386 | wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); | ||
387 | wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); | ||
388 | wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); | ||
389 | wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); | ||
390 | wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); | ||
391 | wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | ||
392 | wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | ||
393 | |||
394 | if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2]) | ||
395 | wacom_report_key(wcombo, wacom->tool[1], 1); | ||
396 | else | ||
397 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
398 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); | ||
399 | return 1; | ||
400 | } | ||
401 | |||
402 | /* process in/out prox events */ | ||
403 | result = wacom_intuos_inout(wacom, wcombo); | ||
404 | if (result) | ||
405 | return result-1; | ||
406 | |||
407 | /* Cintiq doesn't send data when RDY bit isn't set */ | ||
408 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) | ||
409 | return 0; | ||
410 | |||
411 | if (wacom->features->type >= INTUOS3) { | ||
412 | wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | ||
413 | wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | ||
414 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | ||
415 | } else { | ||
416 | wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2])); | ||
417 | wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4])); | ||
418 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); | ||
419 | } | ||
420 | |||
421 | /* process general packets */ | ||
422 | wacom_intuos_general(wacom, wcombo); | ||
423 | |||
424 | /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ | ||
425 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { | ||
426 | |||
427 | if (data[1] & 0x02) { | ||
428 | /* Rotation packet */ | ||
429 | if (wacom->features->type >= INTUOS3) { | ||
430 | /* I3 marker pen rotation reported as wheel | ||
431 | * due to valuator limitation | ||
432 | */ | ||
433 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
434 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | ||
435 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | ||
436 | wacom_report_abs(wcombo, ABS_WHEEL, t); | ||
437 | } else { | ||
438 | /* 4D mouse rotation packet */ | ||
439 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
440 | wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ? | ||
441 | ((t - 1) / 2) : -t / 2); | ||
442 | } | ||
443 | |||
444 | } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) { | ||
445 | /* 4D mouse packet */ | ||
446 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | ||
447 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | ||
448 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); | ||
449 | |||
450 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x20); | ||
451 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x10); | ||
452 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
453 | wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
454 | |||
455 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | ||
456 | /* 2D mouse packet */ | ||
457 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04); | ||
458 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); | ||
459 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10); | ||
460 | wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) | ||
461 | - ((data[8] & 0x02) >> 1)); | ||
462 | |||
463 | /* I3 2D mouse side buttons */ | ||
464 | if (wacom->features->type == INTUOS3) { | ||
465 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); | ||
466 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); | ||
467 | } | ||
468 | |||
469 | } else if (wacom->features->type < INTUOS3) { | ||
470 | /* Lens cursor packets */ | ||
471 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | ||
472 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | ||
473 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); | ||
474 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x10); | ||
475 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x08); | ||
476 | } | ||
477 | } | ||
478 | |||
479 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ | ||
480 | wacom_report_key(wcombo, wacom->tool[idx], 1); | ||
481 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
482 | return 1; | ||
483 | } | ||
484 | |||
485 | int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | ||
486 | { | ||
487 | switch (wacom_wac->features->type) { | ||
488 | case PENPARTNER: | ||
489 | return (wacom_penpartner_irq(wacom_wac, wcombo)); | ||
490 | break; | ||
491 | case PL: | ||
492 | return (wacom_pl_irq(wacom_wac, wcombo)); | ||
493 | break; | ||
494 | case WACOM_G4: | ||
495 | case GRAPHIRE: | ||
496 | return (wacom_graphire_irq(wacom_wac, wcombo)); | ||
497 | break; | ||
498 | case PTU: | ||
499 | return (wacom_ptu_irq(wacom_wac, wcombo)); | ||
500 | break; | ||
501 | case INTUOS: | ||
502 | case INTUOS3: | ||
503 | case INTUOS3L: | ||
504 | case CINTIQ: | ||
505 | return (wacom_intuos_irq(wacom_wac, wcombo)); | ||
506 | break; | ||
507 | default: | ||
508 | return 0; | ||
509 | } | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
514 | { | ||
515 | switch (wacom_wac->features->type) { | ||
516 | case WACOM_G4: | ||
517 | input_dev_g4(input_dev, wacom_wac); | ||
518 | /* fall through */ | ||
519 | case GRAPHIRE: | ||
520 | input_dev_g(input_dev, wacom_wac); | ||
521 | break; | ||
522 | case INTUOS3: | ||
523 | case INTUOS3L: | ||
524 | case CINTIQ: | ||
525 | input_dev_i3(input_dev, wacom_wac); | ||
526 | /* fall through */ | ||
527 | case INTUOS: | ||
528 | input_dev_i(input_dev, wacom_wac); | ||
529 | break; | ||
530 | case PL: | ||
531 | case PTU: | ||
532 | input_dev_pl(input_dev, wacom_wac); | ||
533 | break; | ||
534 | case PENPARTNER: | ||
535 | input_dev_pt(input_dev, wacom_wac); | ||
536 | break; | ||
537 | } | ||
538 | return; | ||
539 | } | ||
540 | |||
541 | static struct wacom_features wacom_features[] = { | ||
542 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_sys_irq }, | ||
543 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
544 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
545 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
546 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
547 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
548 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_sys_irq }, | ||
549 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_sys_irq }, | ||
550 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
551 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_sys_irq }, | ||
552 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
553 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 32, GRAPHIRE, wacom_sys_irq }, | ||
554 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_sys_irq }, | ||
555 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_sys_irq}, | ||
556 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_sys_irq }, | ||
557 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_sys_irq }, | ||
558 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_sys_irq }, | ||
559 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_sys_irq}, | ||
560 | { "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_sys_irq }, | ||
561 | { "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_sys_irq }, | ||
562 | { "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_sys_irq }, | ||
563 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_sys_irq }, | ||
564 | { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_sys_irq }, | ||
565 | { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_sys_irq }, | ||
566 | { "Wacom PL700", 8, 6758, 5406, 511, 32, PL, wacom_sys_irq }, | ||
567 | { "Wacom PL510", 8, 6282, 4762, 511, 32, PL, wacom_sys_irq }, | ||
568 | { "Wacom DTU710", 8, 34080, 27660, 511, 32, PL, wacom_sys_irq }, | ||
569 | { "Wacom DTF521", 8, 6282, 4762, 511, 32, PL, wacom_sys_irq }, | ||
570 | { "Wacom DTF720", 8, 6858, 5506, 511, 32, PL, wacom_sys_irq }, | ||
571 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PTU, wacom_sys_irq }, | ||
572 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_sys_irq }, | ||
573 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_sys_irq }, | ||
574 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_sys_irq }, | ||
575 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_sys_irq }, | ||
576 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_sys_irq }, | ||
577 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_sys_irq }, | ||
578 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_sys_irq }, | ||
579 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_sys_irq }, | ||
580 | { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS3L, wacom_sys_irq }, | ||
581 | { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS3L, wacom_sys_irq }, | ||
582 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 15, INTUOS3, wacom_sys_irq }, | ||
583 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_sys_irq }, | ||
584 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_sys_irq }, | ||
585 | { } | ||
586 | }; | ||
587 | |||
588 | static struct usb_device_id wacom_ids[] = { | ||
589 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, | ||
590 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, | ||
591 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, | ||
592 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, | ||
593 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, | ||
594 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, | ||
595 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, | ||
596 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, | ||
597 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | ||
598 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, | ||
599 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, | ||
600 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, | ||
601 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, | ||
602 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | ||
603 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | ||
604 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | ||
605 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, | ||
606 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, | ||
607 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, | ||
608 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, | ||
609 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, | ||
610 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, | ||
611 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, | ||
612 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, | ||
613 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | ||
614 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | ||
615 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | ||
616 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
617 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, | ||
618 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | ||
619 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | ||
620 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | ||
621 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, | ||
622 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, | ||
623 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, | ||
624 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | ||
625 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | ||
626 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | ||
627 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, | ||
628 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, | ||
629 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, | ||
630 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | ||
631 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | ||
632 | { } | ||
633 | }; | ||
634 | |||
635 | const struct usb_device_id * get_device_table(void) { | ||
636 | const struct usb_device_id * id_table = wacom_ids; | ||
637 | return id_table; | ||
638 | } | ||
639 | |||
640 | struct wacom_features * get_wacom_feature(const struct usb_device_id * id) { | ||
641 | int index = id - wacom_ids; | ||
642 | struct wacom_features *wf = &wacom_features[index]; | ||
643 | return wf; | ||
644 | } | ||
645 | |||
646 | MODULE_DEVICE_TABLE(usb, wacom_ids); | ||
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h new file mode 100644 index 000000000000..ceae7bf59d9f --- /dev/null +++ b/drivers/usb/input/wacom_wac.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * drivers/usb/input/wacom_wac.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | #ifndef WACOM_WAC_H | ||
10 | #define WACOM_WAC_H | ||
11 | |||
12 | #define STYLUS_DEVICE_ID 0x02 | ||
13 | #define CURSOR_DEVICE_ID 0x06 | ||
14 | #define ERASER_DEVICE_ID 0x0A | ||
15 | |||
16 | enum { | ||
17 | PENPARTNER = 0, | ||
18 | GRAPHIRE, | ||
19 | WACOM_G4, | ||
20 | PTU, | ||
21 | PL, | ||
22 | INTUOS, | ||
23 | INTUOS3, | ||
24 | INTUOS3L, | ||
25 | CINTIQ, | ||
26 | MAX_TYPE | ||
27 | }; | ||
28 | |||
29 | struct wacom_features { | ||
30 | char *name; | ||
31 | int pktlen; | ||
32 | int x_max; | ||
33 | int y_max; | ||
34 | int pressure_max; | ||
35 | int distance_max; | ||
36 | int type; | ||
37 | usb_complete_t irq; | ||
38 | }; | ||
39 | |||
40 | struct wacom_wac { | ||
41 | signed char *data; | ||
42 | int tool[2]; | ||
43 | int id[2]; | ||
44 | __u32 serial[2]; | ||
45 | struct wacom_features *features; | ||
46 | }; | ||
47 | |||
48 | #endif | ||
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 7b45fd3de911..7291e7a2717b 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c | |||
@@ -971,7 +971,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
971 | DRIVER_VERSION, sizeof(DRIVER_VERSION)); | 971 | DRIVER_VERSION, sizeof(DRIVER_VERSION)); |
972 | 972 | ||
973 | /* Register sysfs hooks (don't care about failure) */ | 973 | /* Register sysfs hooks (don't care about failure) */ |
974 | sysfs_create_group(&intf->dev.kobj, &yld_attr_group); | 974 | ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group); |
975 | return 0; | 975 | return 0; |
976 | } | 976 | } |
977 | 977 | ||
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 88928a4be805..c29658f69e2a 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig | |||
@@ -32,6 +32,16 @@ config USB_EMI26 | |||
32 | To compile this driver as a module, choose M here: the | 32 | To compile this driver as a module, choose M here: the |
33 | module will be called emi26. | 33 | module will be called emi26. |
34 | 34 | ||
35 | config USB_ADUTUX | ||
36 | tristate "ADU devices from Ontrak Control Systems (EXPERIMENTAL)" | ||
37 | depends on USB && EXPERIMENTAL | ||
38 | help | ||
39 | Say Y if you want to use an ADU device from Ontrak Control | ||
40 | Systems. | ||
41 | |||
42 | To compile this driver as a module, choose M here. The module | ||
43 | will be called adutux. | ||
44 | |||
35 | config USB_AUERSWALD | 45 | config USB_AUERSWALD |
36 | tristate "USB Auerswald ISDN support (EXPERIMENTAL)" | 46 | tristate "USB Auerswald ISDN support (EXPERIMENTAL)" |
37 | depends on USB && EXPERIMENTAL | 47 | depends on USB && EXPERIMENTAL |
@@ -115,19 +125,36 @@ config USB_CYTHERM | |||
115 | To compile this driver as a module, choose M here: the | 125 | To compile this driver as a module, choose M here: the |
116 | module will be called cytherm. | 126 | module will be called cytherm. |
117 | 127 | ||
118 | config USB_PHIDGETKIT | 128 | config USB_PHIDGET |
119 | tristate "USB PhidgetKit support" | 129 | tristate "USB Phidgets drivers" |
120 | depends on USB | 130 | depends on USB |
121 | help | 131 | help |
122 | Say Y here if you want to connect a PhidgetKit USB device from | 132 | Say Y here to enable the various drivers for devices from |
123 | Phidgets Inc. | 133 | Phidgets inc. |
134 | |||
135 | config USB_PHIDGETKIT | ||
136 | tristate "USB PhidgetInterfaceKit support" | ||
137 | depends on USB_PHIDGET | ||
138 | help | ||
139 | Say Y here if you want to connect a PhidgetInterfaceKit USB device | ||
140 | from Phidgets Inc. | ||
124 | 141 | ||
125 | To compile this driver as a module, choose M here: the | 142 | To compile this driver as a module, choose M here: the |
126 | module will be called phidgetkit. | 143 | module will be called phidgetkit. |
127 | 144 | ||
145 | config USB_PHIDGETMOTORCONTROL | ||
146 | tristate "USB PhidgetMotorControl support" | ||
147 | depends on USB_PHIDGET | ||
148 | help | ||
149 | Say Y here if you want to connect a PhidgetMotorControl USB device | ||
150 | from Phidgets Inc. | ||
151 | |||
152 | To compile this driver as a module, choose M here: the | ||
153 | module will be called phidgetmotorcontrol. | ||
154 | |||
128 | config USB_PHIDGETSERVO | 155 | config USB_PHIDGETSERVO |
129 | tristate "USB PhidgetServo support" | 156 | tristate "USB PhidgetServo support" |
130 | depends on USB | 157 | depends on USB_PHIDGET |
131 | help | 158 | help |
132 | Say Y here if you want to connect an 1 or 4 Motor PhidgetServo | 159 | Say Y here if you want to connect an 1 or 4 Motor PhidgetServo |
133 | servo controller version 2.0 or 3.0. | 160 | servo controller version 2.0 or 3.0. |
@@ -151,6 +178,30 @@ config USB_IDMOUSE | |||
151 | 178 | ||
152 | See also <http://www.fs.tum.de/~echtler/idmouse/>. | 179 | See also <http://www.fs.tum.de/~echtler/idmouse/>. |
153 | 180 | ||
181 | config USB_FTDI_ELAN | ||
182 | tristate "Elan PCMCIA CardBus Adapter USB Client" | ||
183 | depends on USB | ||
184 | default M | ||
185 | help | ||
186 | ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters. | ||
187 | Currently only the U132 adapter is available. | ||
188 | |||
189 | The U132 is specifically designed for CardBus PC cards that contain | ||
190 | an OHCI host controller. Typical PC cards are the Orange Mobile 3G | ||
191 | Option GlobeTrotter Fusion card. The U132 adapter will *NOT* work | ||
192 | with PC cards that do not contain an OHCI controller. To use a U132 | ||
193 | adapter you will need this "ftdi-elan" module as well as the "u132-hcd" | ||
194 | module which is a USB host controller driver that talks to the OHCI | ||
195 | controller within CardBus card that are inserted in the U132 adapter. | ||
196 | |||
197 | This driver has been tested with a CardBus OHCI USB adapter, and | ||
198 | worked with a USB PEN Drive inserted into the first USB port of | ||
199 | the PCCARD. A rather pointless thing to do, but useful for testing. | ||
200 | |||
201 | See also the USB_U132_HCD entry "Elan U132 Adapter Host Controller" | ||
202 | |||
203 | It is safe to say M here. | ||
204 | |||
154 | config USB_APPLEDISPLAY | 205 | config USB_APPLEDISPLAY |
155 | tristate "Apple Cinema Display support" | 206 | tristate "Apple Cinema Display support" |
156 | depends on USB | 207 | depends on USB |
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 2927260c5812..2be70fa259bf 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile | |||
@@ -3,22 +3,25 @@ | |||
3 | # (the ones that don't fit into any other categories) | 3 | # (the ones that don't fit into any other categories) |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_USB_ADUTUX) += adutux.o | ||
6 | obj-$(CONFIG_USB_AUERSWALD) += auerswald.o | 7 | obj-$(CONFIG_USB_AUERSWALD) += auerswald.o |
7 | obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o | 8 | obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o |
8 | obj-$(CONFIG_USB_CYTHERM) += cytherm.o | 9 | obj-$(CONFIG_USB_CYTHERM) += cytherm.o |
9 | obj-$(CONFIG_USB_EMI26) += emi26.o | 10 | obj-$(CONFIG_USB_EMI26) += emi26.o |
10 | obj-$(CONFIG_USB_EMI62) += emi62.o | 11 | obj-$(CONFIG_USB_EMI62) += emi62.o |
12 | obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o | ||
11 | obj-$(CONFIG_USB_IDMOUSE) += idmouse.o | 13 | obj-$(CONFIG_USB_IDMOUSE) += idmouse.o |
12 | obj-$(CONFIG_USB_LCD) += usblcd.o | 14 | obj-$(CONFIG_USB_LCD) += usblcd.o |
13 | obj-$(CONFIG_USB_LD) += ldusb.o | 15 | obj-$(CONFIG_USB_LD) += ldusb.o |
14 | obj-$(CONFIG_USB_LED) += usbled.o | 16 | obj-$(CONFIG_USB_LED) += usbled.o |
15 | obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o | 17 | obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o |
18 | obj-$(CONFIG_USB_PHIDGET) += phidget.o | ||
16 | obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o | 19 | obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o |
20 | obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o | ||
17 | obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o | 21 | obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o |
18 | obj-$(CONFIG_USB_RIO500) += rio500.o | 22 | obj-$(CONFIG_USB_RIO500) += rio500.o |
19 | obj-$(CONFIG_USB_TEST) += usbtest.o | 23 | obj-$(CONFIG_USB_TEST) += usbtest.o |
20 | obj-$(CONFIG_USB_USS720) += uss720.o | 24 | obj-$(CONFIG_USB_USS720) += uss720.o |
21 | obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o | ||
22 | 25 | ||
23 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ | 26 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ |
24 | 27 | ||
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c new file mode 100644 index 000000000000..d3963199b6ec --- /dev/null +++ b/drivers/usb/misc/adutux.c | |||
@@ -0,0 +1,900 @@ | |||
1 | /* | ||
2 | * adutux - driver for ADU devices from Ontrak Control Systems | ||
3 | * This is an experimental driver. Use at your own risk. | ||
4 | * This driver is not supported by Ontrak Control Systems. | ||
5 | * | ||
6 | * Copyright (c) 2003 John Homppi (SCO, leave this notice here) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | * | ||
13 | * derived from the Lego USB Tower driver 0.56: | ||
14 | * Copyright (c) 2003 David Glance <davidgsf@sourceforge.net> | ||
15 | * 2001 Juergen Stuber <stuber@loria.fr> | ||
16 | * that was derived from USB Skeleton driver - 0.5 | ||
17 | * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/usb.h> | ||
27 | #include <asm/uaccess.h> | ||
28 | |||
29 | #ifdef CONFIG_USB_DEBUG | ||
30 | static int debug = 5; | ||
31 | #else | ||
32 | static int debug = 1; | ||
33 | #endif | ||
34 | |||
35 | /* Use our own dbg macro */ | ||
36 | #undef dbg | ||
37 | #define dbg(lvl, format, arg...) \ | ||
38 | do { \ | ||
39 | if (debug >= lvl) \ | ||
40 | printk(KERN_DEBUG __FILE__ " : " format " \n", ## arg); \ | ||
41 | } while (0) | ||
42 | |||
43 | |||
44 | /* Version Information */ | ||
45 | #define DRIVER_VERSION "v0.0.13" | ||
46 | #define DRIVER_AUTHOR "John Homppi" | ||
47 | #define DRIVER_DESC "adutux (see www.ontrak.net)" | ||
48 | |||
49 | /* Module parameters */ | ||
50 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
51 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
52 | |||
53 | /* Define these values to match your device */ | ||
54 | #define ADU_VENDOR_ID 0x0a07 | ||
55 | #define ADU_PRODUCT_ID 0x0064 | ||
56 | |||
57 | /* table of devices that work with this driver */ | ||
58 | static struct usb_device_id device_table [] = { | ||
59 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) }, /* ADU100 */ | ||
60 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, /* ADU120 */ | ||
61 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, /* ADU130 */ | ||
62 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) }, /* ADU200 */ | ||
63 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) }, /* ADU208 */ | ||
64 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) }, /* ADU218 */ | ||
65 | { }/* Terminating entry */ | ||
66 | }; | ||
67 | |||
68 | MODULE_DEVICE_TABLE(usb, device_table); | ||
69 | |||
70 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
71 | #define ADU_MINOR_BASE 0 | ||
72 | #else | ||
73 | #define ADU_MINOR_BASE 67 | ||
74 | #endif | ||
75 | |||
76 | /* we can have up to this number of device plugged in at once */ | ||
77 | #define MAX_DEVICES 16 | ||
78 | |||
79 | #define COMMAND_TIMEOUT (2*HZ) /* 60 second timeout for a command */ | ||
80 | |||
81 | /* Structure to hold all of our device specific stuff */ | ||
82 | struct adu_device { | ||
83 | struct semaphore sem; /* locks this structure */ | ||
84 | struct usb_device* udev; /* save off the usb device pointer */ | ||
85 | struct usb_interface* interface; | ||
86 | unsigned char minor; /* the starting minor number for this device */ | ||
87 | char serial_number[8]; | ||
88 | |||
89 | int open_count; /* number of times this port has been opened */ | ||
90 | |||
91 | char* read_buffer_primary; | ||
92 | int read_buffer_length; | ||
93 | char* read_buffer_secondary; | ||
94 | int secondary_head; | ||
95 | int secondary_tail; | ||
96 | spinlock_t buflock; | ||
97 | |||
98 | wait_queue_head_t read_wait; | ||
99 | wait_queue_head_t write_wait; | ||
100 | |||
101 | char* interrupt_in_buffer; | ||
102 | struct usb_endpoint_descriptor* interrupt_in_endpoint; | ||
103 | struct urb* interrupt_in_urb; | ||
104 | int read_urb_finished; | ||
105 | |||
106 | char* interrupt_out_buffer; | ||
107 | struct usb_endpoint_descriptor* interrupt_out_endpoint; | ||
108 | struct urb* interrupt_out_urb; | ||
109 | }; | ||
110 | |||
111 | /* prevent races between open() and disconnect */ | ||
112 | static DEFINE_MUTEX(disconnect_mutex); | ||
113 | static struct usb_driver adu_driver; | ||
114 | |||
115 | static void adu_debug_data(int level, const char *function, int size, | ||
116 | const unsigned char *data) | ||
117 | { | ||
118 | int i; | ||
119 | |||
120 | if (debug < level) | ||
121 | return; | ||
122 | |||
123 | printk(KERN_DEBUG __FILE__": %s - length = %d, data = ", | ||
124 | function, size); | ||
125 | for (i = 0; i < size; ++i) | ||
126 | printk("%.2x ", data[i]); | ||
127 | printk("\n"); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * adu_abort_transfers | ||
132 | * aborts transfers and frees associated data structures | ||
133 | */ | ||
134 | static void adu_abort_transfers(struct adu_device *dev) | ||
135 | { | ||
136 | dbg(2," %s : enter", __FUNCTION__); | ||
137 | |||
138 | if (dev == NULL) { | ||
139 | dbg(1," %s : dev is null", __FUNCTION__); | ||
140 | goto exit; | ||
141 | } | ||
142 | |||
143 | if (dev->udev == NULL) { | ||
144 | dbg(1," %s : udev is null", __FUNCTION__); | ||
145 | goto exit; | ||
146 | } | ||
147 | |||
148 | dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state); | ||
149 | if (dev->udev->state == USB_STATE_NOTATTACHED) { | ||
150 | dbg(1," %s : udev is not attached", __FUNCTION__); | ||
151 | goto exit; | ||
152 | } | ||
153 | |||
154 | /* shutdown transfer */ | ||
155 | usb_unlink_urb(dev->interrupt_in_urb); | ||
156 | usb_unlink_urb(dev->interrupt_out_urb); | ||
157 | |||
158 | exit: | ||
159 | dbg(2," %s : leave", __FUNCTION__); | ||
160 | } | ||
161 | |||
162 | static void adu_delete(struct adu_device *dev) | ||
163 | { | ||
164 | dbg(2, "%s enter", __FUNCTION__); | ||
165 | |||
166 | adu_abort_transfers(dev); | ||
167 | |||
168 | /* free data structures */ | ||
169 | usb_free_urb(dev->interrupt_in_urb); | ||
170 | usb_free_urb(dev->interrupt_out_urb); | ||
171 | kfree(dev->read_buffer_primary); | ||
172 | kfree(dev->read_buffer_secondary); | ||
173 | kfree(dev->interrupt_in_buffer); | ||
174 | kfree(dev->interrupt_out_buffer); | ||
175 | kfree(dev); | ||
176 | |||
177 | dbg(2, "%s : leave", __FUNCTION__); | ||
178 | } | ||
179 | |||
180 | static void adu_interrupt_in_callback(struct urb *urb, struct pt_regs *regs) | ||
181 | { | ||
182 | struct adu_device *dev = urb->context; | ||
183 | |||
184 | dbg(4," %s : enter, status %d", __FUNCTION__, urb->status); | ||
185 | adu_debug_data(5, __FUNCTION__, urb->actual_length, | ||
186 | urb->transfer_buffer); | ||
187 | |||
188 | spin_lock(&dev->buflock); | ||
189 | |||
190 | if (urb->status != 0) { | ||
191 | if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) { | ||
192 | dbg(1," %s : nonzero status received: %d", | ||
193 | __FUNCTION__, urb->status); | ||
194 | } | ||
195 | goto exit; | ||
196 | } | ||
197 | |||
198 | if (urb->actual_length > 0 && dev->interrupt_in_buffer[0] != 0x00) { | ||
199 | if (dev->read_buffer_length < | ||
200 | (4 * le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize)) - | ||
201 | (urb->actual_length)) { | ||
202 | memcpy (dev->read_buffer_primary + | ||
203 | dev->read_buffer_length, | ||
204 | dev->interrupt_in_buffer, urb->actual_length); | ||
205 | |||
206 | dev->read_buffer_length += urb->actual_length; | ||
207 | dbg(2," %s reading %d ", __FUNCTION__, | ||
208 | urb->actual_length); | ||
209 | } else { | ||
210 | dbg(1," %s : read_buffer overflow", __FUNCTION__); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | exit: | ||
215 | dev->read_urb_finished = 1; | ||
216 | spin_unlock(&dev->buflock); | ||
217 | /* always wake up so we recover from errors */ | ||
218 | wake_up_interruptible(&dev->read_wait); | ||
219 | adu_debug_data(5, __FUNCTION__, urb->actual_length, | ||
220 | urb->transfer_buffer); | ||
221 | dbg(4," %s : leave, status %d", __FUNCTION__, urb->status); | ||
222 | } | ||
223 | |||
224 | static void adu_interrupt_out_callback(struct urb *urb, struct pt_regs *regs) | ||
225 | { | ||
226 | struct adu_device *dev = urb->context; | ||
227 | |||
228 | dbg(4," %s : enter, status %d", __FUNCTION__, urb->status); | ||
229 | adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer); | ||
230 | |||
231 | if (urb->status != 0) { | ||
232 | if ((urb->status != -ENOENT) && | ||
233 | (urb->status != -ECONNRESET)) { | ||
234 | dbg(1, " %s :nonzero status received: %d", | ||
235 | __FUNCTION__, urb->status); | ||
236 | } | ||
237 | goto exit; | ||
238 | } | ||
239 | |||
240 | wake_up_interruptible(&dev->write_wait); | ||
241 | exit: | ||
242 | |||
243 | adu_debug_data(5, __FUNCTION__, urb->actual_length, | ||
244 | urb->transfer_buffer); | ||
245 | dbg(4," %s : leave, status %d", __FUNCTION__, urb->status); | ||
246 | } | ||
247 | |||
248 | static int adu_open(struct inode *inode, struct file *file) | ||
249 | { | ||
250 | struct adu_device *dev = NULL; | ||
251 | struct usb_interface *interface; | ||
252 | int subminor; | ||
253 | int retval = 0; | ||
254 | |||
255 | dbg(2,"%s : enter", __FUNCTION__); | ||
256 | |||
257 | subminor = iminor(inode); | ||
258 | |||
259 | mutex_lock(&disconnect_mutex); | ||
260 | |||
261 | interface = usb_find_interface(&adu_driver, subminor); | ||
262 | if (!interface) { | ||
263 | err("%s - error, can't find device for minor %d", | ||
264 | __FUNCTION__, subminor); | ||
265 | retval = -ENODEV; | ||
266 | goto exit_no_device; | ||
267 | } | ||
268 | |||
269 | dev = usb_get_intfdata(interface); | ||
270 | if (!dev) { | ||
271 | retval = -ENODEV; | ||
272 | goto exit_no_device; | ||
273 | } | ||
274 | |||
275 | /* lock this device */ | ||
276 | if ((retval = down_interruptible(&dev->sem))) { | ||
277 | dbg(2, "%s : sem down failed", __FUNCTION__); | ||
278 | goto exit_no_device; | ||
279 | } | ||
280 | |||
281 | /* increment our usage count for the device */ | ||
282 | ++dev->open_count; | ||
283 | dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count); | ||
284 | |||
285 | /* save device in the file's private structure */ | ||
286 | file->private_data = dev; | ||
287 | |||
288 | /* initialize in direction */ | ||
289 | dev->read_buffer_length = 0; | ||
290 | |||
291 | /* fixup first read by having urb waiting for it */ | ||
292 | usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, | ||
293 | usb_rcvintpipe(dev->udev, | ||
294 | dev->interrupt_in_endpoint->bEndpointAddress), | ||
295 | dev->interrupt_in_buffer, | ||
296 | le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), | ||
297 | adu_interrupt_in_callback, dev, | ||
298 | dev->interrupt_in_endpoint->bInterval); | ||
299 | /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ | ||
300 | dev->read_urb_finished = 0; | ||
301 | usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); | ||
302 | /* we ignore failure */ | ||
303 | /* end of fixup for first read */ | ||
304 | |||
305 | up(&dev->sem); | ||
306 | |||
307 | exit_no_device: | ||
308 | mutex_unlock(&disconnect_mutex); | ||
309 | dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); | ||
310 | |||
311 | return retval; | ||
312 | } | ||
313 | |||
314 | static int adu_release_internal(struct adu_device *dev) | ||
315 | { | ||
316 | int retval = 0; | ||
317 | |||
318 | dbg(2," %s : enter", __FUNCTION__); | ||
319 | |||
320 | if (dev->udev == NULL) { | ||
321 | /* the device was unplugged before the file was released */ | ||
322 | adu_delete(dev); | ||
323 | goto exit; | ||
324 | } | ||
325 | |||
326 | /* decrement our usage count for the device */ | ||
327 | --dev->open_count; | ||
328 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); | ||
329 | if (dev->open_count <= 0) { | ||
330 | adu_abort_transfers(dev); | ||
331 | dev->open_count = 0; | ||
332 | } | ||
333 | |||
334 | exit: | ||
335 | dbg(2," %s : leave", __FUNCTION__); | ||
336 | return retval; | ||
337 | } | ||
338 | |||
339 | static int adu_release(struct inode *inode, struct file *file) | ||
340 | { | ||
341 | struct adu_device *dev = NULL; | ||
342 | int retval = 0; | ||
343 | |||
344 | dbg(2," %s : enter", __FUNCTION__); | ||
345 | |||
346 | if (file == NULL) { | ||
347 | dbg(1," %s : file is NULL", __FUNCTION__); | ||
348 | retval = -ENODEV; | ||
349 | goto exit; | ||
350 | } | ||
351 | |||
352 | dev = file->private_data; | ||
353 | |||
354 | if (dev == NULL) { | ||
355 | dbg(1," %s : object is NULL", __FUNCTION__); | ||
356 | retval = -ENODEV; | ||
357 | goto exit; | ||
358 | } | ||
359 | |||
360 | /* lock our device */ | ||
361 | down(&dev->sem); /* not interruptible */ | ||
362 | |||
363 | if (dev->open_count <= 0) { | ||
364 | dbg(1," %s : device not opened", __FUNCTION__); | ||
365 | retval = -ENODEV; | ||
366 | goto exit; | ||
367 | } | ||
368 | |||
369 | /* do the work */ | ||
370 | retval = adu_release_internal(dev); | ||
371 | |||
372 | exit: | ||
373 | up(&dev->sem); | ||
374 | dbg(2," %s : leave, return value %d", __FUNCTION__, retval); | ||
375 | return retval; | ||
376 | } | ||
377 | |||
378 | static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | ||
379 | loff_t *ppos) | ||
380 | { | ||
381 | struct adu_device *dev; | ||
382 | size_t bytes_read = 0; | ||
383 | size_t bytes_to_read = count; | ||
384 | int i; | ||
385 | int retval = 0; | ||
386 | int timeout = 0; | ||
387 | int should_submit = 0; | ||
388 | unsigned long flags; | ||
389 | DECLARE_WAITQUEUE(wait, current); | ||
390 | |||
391 | dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file); | ||
392 | |||
393 | dev = file->private_data; | ||
394 | dbg(2," %s : dev=%p", __FUNCTION__, dev); | ||
395 | /* lock this object */ | ||
396 | if (down_interruptible(&dev->sem)) | ||
397 | return -ERESTARTSYS; | ||
398 | |||
399 | /* verify that the device wasn't unplugged */ | ||
400 | if (dev->udev == NULL || dev->minor == 0) { | ||
401 | retval = -ENODEV; | ||
402 | err("No device or device unplugged %d", retval); | ||
403 | goto exit; | ||
404 | } | ||
405 | |||
406 | /* verify that some data was requested */ | ||
407 | if (count == 0) { | ||
408 | dbg(1," %s : read request of 0 bytes", __FUNCTION__); | ||
409 | goto exit; | ||
410 | } | ||
411 | |||
412 | timeout = COMMAND_TIMEOUT; | ||
413 | dbg(2," %s : about to start looping", __FUNCTION__); | ||
414 | while (bytes_to_read) { | ||
415 | int data_in_secondary = dev->secondary_tail - dev->secondary_head; | ||
416 | dbg(2," %s : while, data_in_secondary=%d, status=%d", | ||
417 | __FUNCTION__, data_in_secondary, | ||
418 | dev->interrupt_in_urb->status); | ||
419 | |||
420 | if (data_in_secondary) { | ||
421 | /* drain secondary buffer */ | ||
422 | int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary; | ||
423 | i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount); | ||
424 | if (i < 0) { | ||
425 | retval = -EFAULT; | ||
426 | goto exit; | ||
427 | } | ||
428 | dev->secondary_head += (amount - i); | ||
429 | bytes_read += (amount - i); | ||
430 | bytes_to_read -= (amount - i); | ||
431 | if (i) { | ||
432 | retval = bytes_read ? bytes_read : -EFAULT; | ||
433 | goto exit; | ||
434 | } | ||
435 | } else { | ||
436 | /* we check the primary buffer */ | ||
437 | spin_lock_irqsave (&dev->buflock, flags); | ||
438 | if (dev->read_buffer_length) { | ||
439 | /* we secure access to the primary */ | ||
440 | char *tmp; | ||
441 | dbg(2," %s : swap, read_buffer_length = %d", | ||
442 | __FUNCTION__, dev->read_buffer_length); | ||
443 | tmp = dev->read_buffer_secondary; | ||
444 | dev->read_buffer_secondary = dev->read_buffer_primary; | ||
445 | dev->read_buffer_primary = tmp; | ||
446 | dev->secondary_head = 0; | ||
447 | dev->secondary_tail = dev->read_buffer_length; | ||
448 | dev->read_buffer_length = 0; | ||
449 | spin_unlock_irqrestore(&dev->buflock, flags); | ||
450 | /* we have a free buffer so use it */ | ||
451 | should_submit = 1; | ||
452 | } else { | ||
453 | /* even the primary was empty - we may need to do IO */ | ||
454 | if (dev->interrupt_in_urb->status == -EINPROGRESS) { | ||
455 | /* somebody is doing IO */ | ||
456 | spin_unlock_irqrestore(&dev->buflock, flags); | ||
457 | dbg(2," %s : submitted already", __FUNCTION__); | ||
458 | } else { | ||
459 | /* we must initiate input */ | ||
460 | dbg(2," %s : initiate input", __FUNCTION__); | ||
461 | dev->read_urb_finished = 0; | ||
462 | |||
463 | usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, | ||
464 | usb_rcvintpipe(dev->udev, | ||
465 | dev->interrupt_in_endpoint->bEndpointAddress), | ||
466 | dev->interrupt_in_buffer, | ||
467 | le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), | ||
468 | adu_interrupt_in_callback, | ||
469 | dev, | ||
470 | dev->interrupt_in_endpoint->bInterval); | ||
471 | retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); | ||
472 | if (!retval) { | ||
473 | spin_unlock_irqrestore(&dev->buflock, flags); | ||
474 | dbg(2," %s : submitted OK", __FUNCTION__); | ||
475 | } else { | ||
476 | if (retval == -ENOMEM) { | ||
477 | retval = bytes_read ? bytes_read : -ENOMEM; | ||
478 | } | ||
479 | spin_unlock_irqrestore(&dev->buflock, flags); | ||
480 | dbg(2," %s : submit failed", __FUNCTION__); | ||
481 | goto exit; | ||
482 | } | ||
483 | } | ||
484 | |||
485 | /* we wait for I/O to complete */ | ||
486 | set_current_state(TASK_INTERRUPTIBLE); | ||
487 | add_wait_queue(&dev->read_wait, &wait); | ||
488 | if (!dev->read_urb_finished) | ||
489 | timeout = schedule_timeout(COMMAND_TIMEOUT); | ||
490 | else | ||
491 | set_current_state(TASK_RUNNING); | ||
492 | remove_wait_queue(&dev->read_wait, &wait); | ||
493 | |||
494 | if (timeout <= 0) { | ||
495 | dbg(2," %s : timeout", __FUNCTION__); | ||
496 | retval = bytes_read ? bytes_read : -ETIMEDOUT; | ||
497 | goto exit; | ||
498 | } | ||
499 | |||
500 | if (signal_pending(current)) { | ||
501 | dbg(2," %s : signal pending", __FUNCTION__); | ||
502 | retval = bytes_read ? bytes_read : -EINTR; | ||
503 | goto exit; | ||
504 | } | ||
505 | } | ||
506 | } | ||
507 | } | ||
508 | |||
509 | retval = bytes_read; | ||
510 | /* if the primary buffer is empty then use it */ | ||
511 | if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) { | ||
512 | usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, | ||
513 | usb_rcvintpipe(dev->udev, | ||
514 | dev->interrupt_in_endpoint->bEndpointAddress), | ||
515 | dev->interrupt_in_buffer, | ||
516 | le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), | ||
517 | adu_interrupt_in_callback, | ||
518 | dev, | ||
519 | dev->interrupt_in_endpoint->bInterval); | ||
520 | /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ | ||
521 | dev->read_urb_finished = 0; | ||
522 | usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); | ||
523 | /* we ignore failure */ | ||
524 | } | ||
525 | |||
526 | exit: | ||
527 | /* unlock the device */ | ||
528 | up(&dev->sem); | ||
529 | |||
530 | dbg(2," %s : leave, return value %d", __FUNCTION__, retval); | ||
531 | return retval; | ||
532 | } | ||
533 | |||
534 | static ssize_t adu_write(struct file *file, const __user char *buffer, | ||
535 | size_t count, loff_t *ppos) | ||
536 | { | ||
537 | struct adu_device *dev; | ||
538 | size_t bytes_written = 0; | ||
539 | size_t bytes_to_write; | ||
540 | size_t buffer_size; | ||
541 | int retval = 0; | ||
542 | int timeout = 0; | ||
543 | |||
544 | dbg(2," %s : enter, count = %Zd", __FUNCTION__, count); | ||
545 | |||
546 | dev = file->private_data; | ||
547 | |||
548 | /* lock this object */ | ||
549 | down_interruptible(&dev->sem); | ||
550 | |||
551 | /* verify that the device wasn't unplugged */ | ||
552 | if (dev->udev == NULL || dev->minor == 0) { | ||
553 | retval = -ENODEV; | ||
554 | err("No device or device unplugged %d", retval); | ||
555 | goto exit; | ||
556 | } | ||
557 | |||
558 | /* verify that we actually have some data to write */ | ||
559 | if (count == 0) { | ||
560 | dbg(1," %s : write request of 0 bytes", __FUNCTION__); | ||
561 | goto exit; | ||
562 | } | ||
563 | |||
564 | |||
565 | while (count > 0) { | ||
566 | if (dev->interrupt_out_urb->status == -EINPROGRESS) { | ||
567 | timeout = COMMAND_TIMEOUT; | ||
568 | |||
569 | while (timeout > 0) { | ||
570 | if (signal_pending(current)) { | ||
571 | dbg(1," %s : interrupted", __FUNCTION__); | ||
572 | retval = -EINTR; | ||
573 | goto exit; | ||
574 | } | ||
575 | up(&dev->sem); | ||
576 | timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout); | ||
577 | down_interruptible(&dev->sem); | ||
578 | if (timeout > 0) { | ||
579 | break; | ||
580 | } | ||
581 | dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout); | ||
582 | } | ||
583 | |||
584 | |||
585 | dbg(1," %s : final timeout: %d", __FUNCTION__, timeout); | ||
586 | |||
587 | if (timeout == 0) { | ||
588 | dbg(1, "%s - command timed out.", __FUNCTION__); | ||
589 | retval = -ETIMEDOUT; | ||
590 | goto exit; | ||
591 | } | ||
592 | |||
593 | dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count); | ||
594 | |||
595 | } else { | ||
596 | dbg(4," %s : sending, count = %Zd", __FUNCTION__, count); | ||
597 | |||
598 | /* write the data into interrupt_out_buffer from userspace */ | ||
599 | buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize); | ||
600 | bytes_to_write = count > buffer_size ? buffer_size : count; | ||
601 | dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", | ||
602 | __FUNCTION__, buffer_size, count, bytes_to_write); | ||
603 | |||
604 | if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) { | ||
605 | retval = -EFAULT; | ||
606 | goto exit; | ||
607 | } | ||
608 | |||
609 | /* send off the urb */ | ||
610 | usb_fill_int_urb( | ||
611 | dev->interrupt_out_urb, | ||
612 | dev->udev, | ||
613 | usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress), | ||
614 | dev->interrupt_out_buffer, | ||
615 | bytes_to_write, | ||
616 | adu_interrupt_out_callback, | ||
617 | dev, | ||
618 | dev->interrupt_in_endpoint->bInterval); | ||
619 | /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ | ||
620 | dev->interrupt_out_urb->actual_length = bytes_to_write; | ||
621 | retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); | ||
622 | if (retval < 0) { | ||
623 | err("Couldn't submit interrupt_out_urb %d", retval); | ||
624 | goto exit; | ||
625 | } | ||
626 | |||
627 | buffer += bytes_to_write; | ||
628 | count -= bytes_to_write; | ||
629 | |||
630 | bytes_written += bytes_to_write; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | retval = bytes_written; | ||
635 | |||
636 | exit: | ||
637 | /* unlock the device */ | ||
638 | up(&dev->sem); | ||
639 | |||
640 | dbg(2," %s : leave, return value %d", __FUNCTION__, retval); | ||
641 | |||
642 | return retval; | ||
643 | } | ||
644 | |||
645 | /* file operations needed when we register this driver */ | ||
646 | static struct file_operations adu_fops = { | ||
647 | .owner = THIS_MODULE, | ||
648 | .read = adu_read, | ||
649 | .write = adu_write, | ||
650 | .open = adu_open, | ||
651 | .release = adu_release, | ||
652 | }; | ||
653 | |||
654 | /* | ||
655 | * usb class driver info in order to get a minor number from the usb core, | ||
656 | * and to have the device registered with devfs and the driver core | ||
657 | */ | ||
658 | static struct usb_class_driver adu_class = { | ||
659 | .name = "usb/adutux%d", | ||
660 | .fops = &adu_fops, | ||
661 | .minor_base = ADU_MINOR_BASE, | ||
662 | }; | ||
663 | |||
664 | /** | ||
665 | * adu_probe | ||
666 | * | ||
667 | * Called by the usb core when a new device is connected that it thinks | ||
668 | * this driver might be interested in. | ||
669 | */ | ||
670 | static int adu_probe(struct usb_interface *interface, | ||
671 | const struct usb_device_id *id) | ||
672 | { | ||
673 | struct usb_device *udev = interface_to_usbdev(interface); | ||
674 | struct adu_device *dev = NULL; | ||
675 | struct usb_host_interface *iface_desc; | ||
676 | struct usb_endpoint_descriptor *endpoint; | ||
677 | int retval = -ENODEV; | ||
678 | int in_end_size; | ||
679 | int out_end_size; | ||
680 | int i; | ||
681 | |||
682 | dbg(2," %s : enter", __FUNCTION__); | ||
683 | |||
684 | if (udev == NULL) { | ||
685 | dev_err(&interface->dev, "udev is NULL.\n"); | ||
686 | goto exit; | ||
687 | } | ||
688 | |||
689 | /* allocate memory for our device state and intialize it */ | ||
690 | dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL); | ||
691 | if (dev == NULL) { | ||
692 | dev_err(&interface->dev, "Out of memory\n"); | ||
693 | retval = -ENOMEM; | ||
694 | goto exit; | ||
695 | } | ||
696 | |||
697 | init_MUTEX(&dev->sem); | ||
698 | spin_lock_init(&dev->buflock); | ||
699 | dev->udev = udev; | ||
700 | init_waitqueue_head(&dev->read_wait); | ||
701 | init_waitqueue_head(&dev->write_wait); | ||
702 | |||
703 | iface_desc = &interface->altsetting[0]; | ||
704 | |||
705 | /* set up the endpoint information */ | ||
706 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
707 | endpoint = &iface_desc->endpoint[i].desc; | ||
708 | |||
709 | if (usb_endpoint_is_int_in(endpoint)) | ||
710 | dev->interrupt_in_endpoint = endpoint; | ||
711 | |||
712 | if (usb_endpoint_is_int_out(endpoint)) | ||
713 | dev->interrupt_out_endpoint = endpoint; | ||
714 | } | ||
715 | if (dev->interrupt_in_endpoint == NULL) { | ||
716 | dev_err(&interface->dev, "interrupt in endpoint not found\n"); | ||
717 | goto error; | ||
718 | } | ||
719 | if (dev->interrupt_out_endpoint == NULL) { | ||
720 | dev_err(&interface->dev, "interrupt out endpoint not found\n"); | ||
721 | goto error; | ||
722 | } | ||
723 | |||
724 | in_end_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); | ||
725 | out_end_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize); | ||
726 | |||
727 | dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL); | ||
728 | if (!dev->read_buffer_primary) { | ||
729 | dev_err(&interface->dev, "Couldn't allocate read_buffer_primary\n"); | ||
730 | retval = -ENOMEM; | ||
731 | goto error; | ||
732 | } | ||
733 | |||
734 | /* debug code prime the buffer */ | ||
735 | memset(dev->read_buffer_primary, 'a', in_end_size); | ||
736 | memset(dev->read_buffer_primary + in_end_size, 'b', in_end_size); | ||
737 | memset(dev->read_buffer_primary + (2 * in_end_size), 'c', in_end_size); | ||
738 | memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size); | ||
739 | |||
740 | dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL); | ||
741 | if (!dev->read_buffer_secondary) { | ||
742 | dev_err(&interface->dev, "Couldn't allocate read_buffer_secondary\n"); | ||
743 | retval = -ENOMEM; | ||
744 | goto error; | ||
745 | } | ||
746 | |||
747 | /* debug code prime the buffer */ | ||
748 | memset(dev->read_buffer_secondary, 'e', in_end_size); | ||
749 | memset(dev->read_buffer_secondary + in_end_size, 'f', in_end_size); | ||
750 | memset(dev->read_buffer_secondary + (2 * in_end_size), 'g', in_end_size); | ||
751 | memset(dev->read_buffer_secondary + (3 * in_end_size), 'h', in_end_size); | ||
752 | |||
753 | dev->interrupt_in_buffer = kmalloc(in_end_size, GFP_KERNEL); | ||
754 | if (!dev->interrupt_in_buffer) { | ||
755 | dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n"); | ||
756 | goto error; | ||
757 | } | ||
758 | |||
759 | /* debug code prime the buffer */ | ||
760 | memset(dev->interrupt_in_buffer, 'i', in_end_size); | ||
761 | |||
762 | dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
763 | if (!dev->interrupt_in_urb) { | ||
764 | dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n"); | ||
765 | goto error; | ||
766 | } | ||
767 | dev->interrupt_out_buffer = kmalloc(out_end_size, GFP_KERNEL); | ||
768 | if (!dev->interrupt_out_buffer) { | ||
769 | dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n"); | ||
770 | goto error; | ||
771 | } | ||
772 | dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
773 | if (!dev->interrupt_out_urb) { | ||
774 | dev_err(&interface->dev, "Couldn't allocate interrupt_out_urb\n"); | ||
775 | goto error; | ||
776 | } | ||
777 | |||
778 | if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number, | ||
779 | sizeof(dev->serial_number))) { | ||
780 | dev_err(&interface->dev, "Could not retrieve serial number\n"); | ||
781 | goto error; | ||
782 | } | ||
783 | dbg(2," %s : serial_number=%s", __FUNCTION__, dev->serial_number); | ||
784 | |||
785 | /* we can register the device now, as it is ready */ | ||
786 | usb_set_intfdata(interface, dev); | ||
787 | |||
788 | retval = usb_register_dev(interface, &adu_class); | ||
789 | |||
790 | if (retval) { | ||
791 | /* something prevented us from registering this driver */ | ||
792 | dev_err(&interface->dev, "Not able to get a minor for this device.\n"); | ||
793 | usb_set_intfdata(interface, NULL); | ||
794 | goto error; | ||
795 | } | ||
796 | |||
797 | dev->minor = interface->minor; | ||
798 | |||
799 | /* let the user know what node this device is now attached to */ | ||
800 | dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d", | ||
801 | udev->descriptor.idProduct, dev->serial_number, | ||
802 | (dev->minor - ADU_MINOR_BASE)); | ||
803 | exit: | ||
804 | dbg(2," %s : leave, return value %p (dev)", __FUNCTION__, dev); | ||
805 | |||
806 | return retval; | ||
807 | |||
808 | error: | ||
809 | adu_delete(dev); | ||
810 | return retval; | ||
811 | } | ||
812 | |||
813 | /** | ||
814 | * adu_disconnect | ||
815 | * | ||
816 | * Called by the usb core when the device is removed from the system. | ||
817 | */ | ||
818 | static void adu_disconnect(struct usb_interface *interface) | ||
819 | { | ||
820 | struct adu_device *dev; | ||
821 | int minor; | ||
822 | |||
823 | dbg(2," %s : enter", __FUNCTION__); | ||
824 | |||
825 | mutex_lock(&disconnect_mutex); /* not interruptible */ | ||
826 | |||
827 | dev = usb_get_intfdata(interface); | ||
828 | usb_set_intfdata(interface, NULL); | ||
829 | |||
830 | down(&dev->sem); /* not interruptible */ | ||
831 | |||
832 | minor = dev->minor; | ||
833 | |||
834 | /* give back our minor */ | ||
835 | usb_deregister_dev(interface, &adu_class); | ||
836 | dev->minor = 0; | ||
837 | |||
838 | /* if the device is not opened, then we clean up right now */ | ||
839 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); | ||
840 | if (!dev->open_count) { | ||
841 | up(&dev->sem); | ||
842 | adu_delete(dev); | ||
843 | } else { | ||
844 | dev->udev = NULL; | ||
845 | up(&dev->sem); | ||
846 | } | ||
847 | |||
848 | mutex_unlock(&disconnect_mutex); | ||
849 | |||
850 | dev_info(&interface->dev, "ADU device adutux%d now disconnected", | ||
851 | (minor - ADU_MINOR_BASE)); | ||
852 | |||
853 | dbg(2," %s : leave", __FUNCTION__); | ||
854 | } | ||
855 | |||
856 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
857 | static struct usb_driver adu_driver = { | ||
858 | .name = "adutux", | ||
859 | .probe = adu_probe, | ||
860 | .disconnect = adu_disconnect, | ||
861 | .id_table = device_table, | ||
862 | }; | ||
863 | |||
864 | static int __init adu_init(void) | ||
865 | { | ||
866 | int result; | ||
867 | |||
868 | dbg(2," %s : enter", __FUNCTION__); | ||
869 | |||
870 | /* register this driver with the USB subsystem */ | ||
871 | result = usb_register(&adu_driver); | ||
872 | if (result < 0) { | ||
873 | err("usb_register failed for the "__FILE__" driver. " | ||
874 | "Error number %d", result); | ||
875 | goto exit; | ||
876 | } | ||
877 | |||
878 | info("adutux " DRIVER_DESC " " DRIVER_VERSION); | ||
879 | info("adutux is an experimental driver. Use at your own risk"); | ||
880 | |||
881 | exit: | ||
882 | dbg(2," %s : leave, return value %d", __FUNCTION__, result); | ||
883 | |||
884 | return result; | ||
885 | } | ||
886 | |||
887 | static void __exit adu_exit(void) | ||
888 | { | ||
889 | dbg(2," %s : enter", __FUNCTION__); | ||
890 | /* deregister this driver with the USB subsystem */ | ||
891 | usb_deregister(&adu_driver); | ||
892 | dbg(2," %s : leave", __FUNCTION__); | ||
893 | } | ||
894 | |||
895 | module_init(adu_init); | ||
896 | module_exit(adu_exit); | ||
897 | |||
898 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
899 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
900 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 1fef36e71c57..4fd2110b3411 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c | |||
@@ -806,7 +806,7 @@ static void auerbuf_releasebuf( pauerbuf_t bp) | |||
806 | 0 Initial, OK | 806 | 0 Initial, OK |
807 | -EINPROGRESS during submission until end | 807 | -EINPROGRESS during submission until end |
808 | -ENOENT if urb is unlinked | 808 | -ENOENT if urb is unlinked |
809 | -ETIMEDOUT Transfer timed out, NAK | 809 | -ETIME Device did not respond |
810 | -ENOMEM Memory Overflow | 810 | -ENOMEM Memory Overflow |
811 | -ENODEV Specified USB-device or bus doesn't exist | 811 | -ENODEV Specified USB-device or bus doesn't exist |
812 | -ENXIO URB already queued | 812 | -ENXIO URB already queued |
@@ -832,7 +832,7 @@ static int auerswald_status_retry (int status) | |||
832 | { | 832 | { |
833 | switch (status) { | 833 | switch (status) { |
834 | case 0: | 834 | case 0: |
835 | case -ETIMEDOUT: | 835 | case -ETIME: |
836 | case -EOVERFLOW: | 836 | case -EOVERFLOW: |
837 | case -EAGAIN: | 837 | case -EAGAIN: |
838 | case -EPIPE: | 838 | case -EPIPE: |
@@ -1858,7 +1858,7 @@ static int auerchar_release (struct inode *inode, struct file *file) | |||
1858 | 1858 | ||
1859 | /*----------------------------------------------------------------------*/ | 1859 | /*----------------------------------------------------------------------*/ |
1860 | /* File operation structure */ | 1860 | /* File operation structure */ |
1861 | static struct file_operations auerswald_fops = | 1861 | static const struct file_operations auerswald_fops = |
1862 | { | 1862 | { |
1863 | .owner = THIS_MODULE, | 1863 | .owner = THIS_MODULE, |
1864 | .llseek = no_llseek, | 1864 | .llseek = no_llseek, |
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c index 9c46746d5d00..b63b5f34b2aa 100644 --- a/drivers/usb/misc/cypress_cy7c63.c +++ b/drivers/usb/misc/cypress_cy7c63.c | |||
@@ -209,7 +209,7 @@ static int cypress_probe(struct usb_interface *interface, | |||
209 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 209 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
210 | if (dev == NULL) { | 210 | if (dev == NULL) { |
211 | dev_err(&interface->dev, "Out of memory!\n"); | 211 | dev_err(&interface->dev, "Out of memory!\n"); |
212 | goto error; | 212 | goto error_mem; |
213 | } | 213 | } |
214 | 214 | ||
215 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 215 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
@@ -218,15 +218,26 @@ static int cypress_probe(struct usb_interface *interface, | |||
218 | usb_set_intfdata(interface, dev); | 218 | usb_set_intfdata(interface, dev); |
219 | 219 | ||
220 | /* create device attribute files */ | 220 | /* create device attribute files */ |
221 | device_create_file(&interface->dev, &dev_attr_port0); | 221 | retval = device_create_file(&interface->dev, &dev_attr_port0); |
222 | device_create_file(&interface->dev, &dev_attr_port1); | 222 | if (retval) |
223 | goto error; | ||
224 | retval = device_create_file(&interface->dev, &dev_attr_port1); | ||
225 | if (retval) | ||
226 | goto error; | ||
223 | 227 | ||
224 | /* let the user know that the device is now attached */ | 228 | /* let the user know that the device is now attached */ |
225 | dev_info(&interface->dev, | 229 | dev_info(&interface->dev, |
226 | "Cypress CY7C63xxx device now attached\n"); | 230 | "Cypress CY7C63xxx device now attached\n"); |
231 | return 0; | ||
227 | 232 | ||
228 | retval = 0; | ||
229 | error: | 233 | error: |
234 | device_remove_file(&interface->dev, &dev_attr_port0); | ||
235 | device_remove_file(&interface->dev, &dev_attr_port1); | ||
236 | usb_set_intfdata(interface, NULL); | ||
237 | usb_put_dev(dev->udev); | ||
238 | kfree(dev); | ||
239 | |||
240 | error_mem: | ||
230 | return retval; | 241 | return retval; |
231 | } | 242 | } |
232 | 243 | ||
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c index b20bec445552..04e87acd6e46 100644 --- a/drivers/usb/misc/cytherm.c +++ b/drivers/usb/misc/cytherm.c | |||
@@ -353,7 +353,7 @@ static int cytherm_probe(struct usb_interface *interface, | |||
353 | dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL); | 353 | dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL); |
354 | if (dev == NULL) { | 354 | if (dev == NULL) { |
355 | dev_err (&interface->dev, "Out of memory\n"); | 355 | dev_err (&interface->dev, "Out of memory\n"); |
356 | goto error; | 356 | goto error_mem; |
357 | } | 357 | } |
358 | 358 | ||
359 | dev->udev = usb_get_dev(udev); | 359 | dev->udev = usb_get_dev(udev); |
@@ -362,18 +362,35 @@ static int cytherm_probe(struct usb_interface *interface, | |||
362 | 362 | ||
363 | dev->brightness = 0xFF; | 363 | dev->brightness = 0xFF; |
364 | 364 | ||
365 | device_create_file(&interface->dev, &dev_attr_brightness); | 365 | retval = device_create_file(&interface->dev, &dev_attr_brightness); |
366 | device_create_file(&interface->dev, &dev_attr_temp); | 366 | if (retval) |
367 | device_create_file(&interface->dev, &dev_attr_button); | 367 | goto error; |
368 | device_create_file(&interface->dev, &dev_attr_port0); | 368 | retval = device_create_file(&interface->dev, &dev_attr_temp); |
369 | device_create_file(&interface->dev, &dev_attr_port1); | 369 | if (retval) |
370 | goto error; | ||
371 | retval = device_create_file(&interface->dev, &dev_attr_button); | ||
372 | if (retval) | ||
373 | goto error; | ||
374 | retval = device_create_file(&interface->dev, &dev_attr_port0); | ||
375 | if (retval) | ||
376 | goto error; | ||
377 | retval = device_create_file(&interface->dev, &dev_attr_port1); | ||
378 | if (retval) | ||
379 | goto error; | ||
370 | 380 | ||
371 | dev_info (&interface->dev, | 381 | dev_info (&interface->dev, |
372 | "Cypress thermometer device now attached\n"); | 382 | "Cypress thermometer device now attached\n"); |
373 | return 0; | 383 | return 0; |
374 | 384 | error: | |
375 | error: | 385 | device_remove_file(&interface->dev, &dev_attr_brightness); |
386 | device_remove_file(&interface->dev, &dev_attr_temp); | ||
387 | device_remove_file(&interface->dev, &dev_attr_button); | ||
388 | device_remove_file(&interface->dev, &dev_attr_port0); | ||
389 | device_remove_file(&interface->dev, &dev_attr_port1); | ||
390 | usb_set_intfdata (interface, NULL); | ||
391 | usb_put_dev(dev->udev); | ||
376 | kfree(dev); | 392 | kfree(dev); |
393 | error_mem: | ||
377 | return retval; | 394 | return retval; |
378 | } | 395 | } |
379 | 396 | ||
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c new file mode 100644 index 000000000000..b88a09497c28 --- /dev/null +++ b/drivers/usb/misc/ftdi-elan.c | |||
@@ -0,0 +1,2809 @@ | |||
1 | /* | ||
2 | * USB FTDI client driver for Elan Digital Systems's Uxxx adapters | ||
3 | * | ||
4 | * Copyright(C) 2006 Elan Digital Systems Limited | ||
5 | * http://www.elandigitalsystems.com | ||
6 | * | ||
7 | * Author and Maintainer - Tony Olech - Elan Digital Systems | ||
8 | * tony.olech@elandigitalsystems.com | ||
9 | * | ||
10 | * This program is free software;you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation, version 2. | ||
13 | * | ||
14 | * | ||
15 | * This driver was written by Tony Olech(tony.olech@elandigitalsystems.com) | ||
16 | * based on various USB client drivers in the 2.6.15 linux kernel | ||
17 | * with constant reference to the 3rd Edition of Linux Device Drivers | ||
18 | * published by O'Reilly | ||
19 | * | ||
20 | * The U132 adapter is a USB to CardBus adapter specifically designed | ||
21 | * for PC cards that contain an OHCI host controller. Typical PC cards | ||
22 | * are the Orange Mobile 3G Option GlobeTrotter Fusion card. | ||
23 | * | ||
24 | * The U132 adapter will *NOT *work with PC cards that do not contain | ||
25 | * an OHCI controller. A simple way to test whether a PC card has an | ||
26 | * OHCI controller as an interface is to insert the PC card directly | ||
27 | * into a laptop(or desktop) with a CardBus slot and if "lspci" shows | ||
28 | * a new USB controller and "lsusb -v" shows a new OHCI Host Controller | ||
29 | * then there is a good chance that the U132 adapter will support the | ||
30 | * PC card.(you also need the specific client driver for the PC card) | ||
31 | * | ||
32 | * Please inform the Author and Maintainer about any PC cards that | ||
33 | * contain OHCI Host Controller and work when directly connected to | ||
34 | * an embedded CardBus slot but do not work when they are connected | ||
35 | * via an ELAN U132 adapter. | ||
36 | * | ||
37 | */ | ||
38 | #include <linux/config.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/errno.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/list.h> | ||
43 | #include <linux/ioctl.h> | ||
44 | #include <linux/slab.h> | ||
45 | #include <linux/module.h> | ||
46 | #include <linux/kref.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | #include <linux/usb.h> | ||
49 | #include <linux/workqueue.h> | ||
50 | #include <linux/platform_device.h> | ||
51 | MODULE_AUTHOR("Tony Olech"); | ||
52 | MODULE_DESCRIPTION("FTDI ELAN driver"); | ||
53 | MODULE_LICENSE("GPL"); | ||
54 | #define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444) | ||
55 | extern struct platform_driver u132_platform_driver; | ||
56 | static struct workqueue_struct *status_queue; | ||
57 | static struct workqueue_struct *command_queue; | ||
58 | static struct workqueue_struct *respond_queue; | ||
59 | /* | ||
60 | * ftdi_module_lock exists to protect access to global variables | ||
61 | * | ||
62 | */ | ||
63 | static struct semaphore ftdi_module_lock; | ||
64 | static int ftdi_instances = 0; | ||
65 | static struct list_head ftdi_static_list; | ||
66 | /* | ||
67 | * end of the global variables protected by ftdi_module_lock | ||
68 | */ | ||
69 | #include "usb_u132.h" | ||
70 | #define TD_DEVNOTRESP 5 | ||
71 | /* Define these values to match your devices*/ | ||
72 | #define USB_FTDI_ELAN_VENDOR_ID 0x0403 | ||
73 | #define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea | ||
74 | /* table of devices that work with this driver*/ | ||
75 | static struct usb_device_id ftdi_elan_table[] = { | ||
76 | {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)}, | ||
77 | { /* Terminating entry */ } | ||
78 | }; | ||
79 | |||
80 | MODULE_DEVICE_TABLE(usb, ftdi_elan_table); | ||
81 | /* only the jtag(firmware upgrade device) interface requires | ||
82 | * a device file and corresponding minor number, but the | ||
83 | * interface is created unconditionally - I suppose it could | ||
84 | * be configured or not according to a module parameter. | ||
85 | * But since we(now) require one interface per device, | ||
86 | * and since it unlikely that a normal installation would | ||
87 | * require more than a couple of elan-ftdi devices, 8 seems | ||
88 | * like a reasonable limit to have here, and if someone | ||
89 | * really requires more than 8 devices, then they can frig the | ||
90 | * code and recompile | ||
91 | */ | ||
92 | #define USB_FTDI_ELAN_MINOR_BASE 192 | ||
93 | #define COMMAND_BITS 5 | ||
94 | #define COMMAND_SIZE (1<<COMMAND_BITS) | ||
95 | #define COMMAND_MASK (COMMAND_SIZE-1) | ||
96 | struct u132_command { | ||
97 | u8 header; | ||
98 | u16 length; | ||
99 | u8 address; | ||
100 | u8 width; | ||
101 | u32 value; | ||
102 | int follows; | ||
103 | void *buffer; | ||
104 | }; | ||
105 | #define RESPOND_BITS 5 | ||
106 | #define RESPOND_SIZE (1<<RESPOND_BITS) | ||
107 | #define RESPOND_MASK (RESPOND_SIZE-1) | ||
108 | struct u132_respond { | ||
109 | u8 header; | ||
110 | u8 address; | ||
111 | u32 *value; | ||
112 | int *result; | ||
113 | struct completion wait_completion; | ||
114 | }; | ||
115 | struct u132_target { | ||
116 | void *endp; | ||
117 | struct urb *urb; | ||
118 | int toggle_bits; | ||
119 | int error_count; | ||
120 | int condition_code; | ||
121 | int repeat_number; | ||
122 | int halted; | ||
123 | int skipped; | ||
124 | int actual; | ||
125 | int non_null; | ||
126 | int active; | ||
127 | int abandoning; | ||
128 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
129 | int toggle_bits, int error_count, int condition_code, | ||
130 | int repeat_number, int halted, int skipped, int actual, | ||
131 | int non_null); | ||
132 | }; | ||
133 | /* Structure to hold all of our device specific stuff*/ | ||
134 | struct usb_ftdi { | ||
135 | struct list_head ftdi_list; | ||
136 | struct semaphore u132_lock; | ||
137 | int command_next; | ||
138 | int command_head; | ||
139 | struct u132_command command[COMMAND_SIZE]; | ||
140 | int respond_next; | ||
141 | int respond_head; | ||
142 | struct u132_respond respond[RESPOND_SIZE]; | ||
143 | struct u132_target target[4]; | ||
144 | char device_name[16]; | ||
145 | unsigned synchronized:1; | ||
146 | unsigned enumerated:1; | ||
147 | unsigned registered:1; | ||
148 | unsigned initialized:1; | ||
149 | unsigned card_ejected:1; | ||
150 | int function; | ||
151 | int sequence_num; | ||
152 | int disconnected; | ||
153 | int gone_away; | ||
154 | int stuck_status; | ||
155 | int status_queue_delay; | ||
156 | struct semaphore sw_lock; | ||
157 | struct usb_device *udev; | ||
158 | struct usb_interface *interface; | ||
159 | struct usb_class_driver *class; | ||
160 | struct work_struct status_work; | ||
161 | struct work_struct command_work; | ||
162 | struct work_struct respond_work; | ||
163 | struct u132_platform_data platform_data; | ||
164 | struct resource resources[0]; | ||
165 | struct platform_device platform_dev; | ||
166 | unsigned char *bulk_in_buffer; | ||
167 | size_t bulk_in_size; | ||
168 | size_t bulk_in_last; | ||
169 | size_t bulk_in_left; | ||
170 | __u8 bulk_in_endpointAddr; | ||
171 | __u8 bulk_out_endpointAddr; | ||
172 | struct kref kref; | ||
173 | u32 controlreg; | ||
174 | u8 response[4 + 1024]; | ||
175 | int expected; | ||
176 | int recieved; | ||
177 | int ed_found; | ||
178 | }; | ||
179 | #define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref) | ||
180 | #define platform_device_to_usb_ftdi(d) container_of(d, struct usb_ftdi, \ | ||
181 | platform_dev) | ||
182 | static struct usb_driver ftdi_elan_driver; | ||
183 | static void ftdi_elan_delete(struct kref *kref) | ||
184 | { | ||
185 | struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref); | ||
186 | dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi); | ||
187 | usb_put_dev(ftdi->udev); | ||
188 | ftdi->disconnected += 1; | ||
189 | down(&ftdi_module_lock); | ||
190 | list_del_init(&ftdi->ftdi_list); | ||
191 | ftdi_instances -= 1; | ||
192 | up(&ftdi_module_lock); | ||
193 | kfree(ftdi->bulk_in_buffer); | ||
194 | ftdi->bulk_in_buffer = NULL; | ||
195 | } | ||
196 | |||
197 | static void ftdi_elan_put_kref(struct usb_ftdi *ftdi) | ||
198 | { | ||
199 | kref_put(&ftdi->kref, ftdi_elan_delete); | ||
200 | } | ||
201 | |||
202 | static void ftdi_elan_get_kref(struct usb_ftdi *ftdi) | ||
203 | { | ||
204 | kref_get(&ftdi->kref); | ||
205 | } | ||
206 | |||
207 | static void ftdi_elan_init_kref(struct usb_ftdi *ftdi) | ||
208 | { | ||
209 | kref_init(&ftdi->kref); | ||
210 | } | ||
211 | |||
212 | static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) | ||
213 | { | ||
214 | if (delta > 0) { | ||
215 | if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) | ||
216 | return; | ||
217 | } else if (queue_work(status_queue, &ftdi->status_work)) | ||
218 | return; | ||
219 | kref_put(&ftdi->kref, ftdi_elan_delete); | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta) | ||
224 | { | ||
225 | if (delta > 0) { | ||
226 | if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) | ||
227 | kref_get(&ftdi->kref); | ||
228 | } else if (queue_work(status_queue, &ftdi->status_work)) | ||
229 | kref_get(&ftdi->kref); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) | ||
234 | { | ||
235 | if (cancel_delayed_work(&ftdi->status_work)) | ||
236 | kref_put(&ftdi->kref, ftdi_elan_delete); | ||
237 | } | ||
238 | |||
239 | static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) | ||
240 | { | ||
241 | if (delta > 0) { | ||
242 | if (queue_delayed_work(command_queue, &ftdi->command_work, | ||
243 | delta)) | ||
244 | return; | ||
245 | } else if (queue_work(command_queue, &ftdi->command_work)) | ||
246 | return; | ||
247 | kref_put(&ftdi->kref, ftdi_elan_delete); | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta) | ||
252 | { | ||
253 | if (delta > 0) { | ||
254 | if (queue_delayed_work(command_queue, &ftdi->command_work, | ||
255 | delta)) | ||
256 | kref_get(&ftdi->kref); | ||
257 | } else if (queue_work(command_queue, &ftdi->command_work)) | ||
258 | kref_get(&ftdi->kref); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) | ||
263 | { | ||
264 | if (cancel_delayed_work(&ftdi->command_work)) | ||
265 | kref_put(&ftdi->kref, ftdi_elan_delete); | ||
266 | } | ||
267 | |||
268 | static void ftdi_response_requeue_work(struct usb_ftdi *ftdi, | ||
269 | unsigned int delta) | ||
270 | { | ||
271 | if (delta > 0) { | ||
272 | if (queue_delayed_work(respond_queue, &ftdi->respond_work, | ||
273 | delta)) | ||
274 | return; | ||
275 | } else if (queue_work(respond_queue, &ftdi->respond_work)) | ||
276 | return; | ||
277 | kref_put(&ftdi->kref, ftdi_elan_delete); | ||
278 | return; | ||
279 | } | ||
280 | |||
281 | static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta) | ||
282 | { | ||
283 | if (delta > 0) { | ||
284 | if (queue_delayed_work(respond_queue, &ftdi->respond_work, | ||
285 | delta)) | ||
286 | kref_get(&ftdi->kref); | ||
287 | } else if (queue_work(respond_queue, &ftdi->respond_work)) | ||
288 | kref_get(&ftdi->kref); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | static void ftdi_response_cancel_work(struct usb_ftdi *ftdi) | ||
293 | { | ||
294 | if (cancel_delayed_work(&ftdi->respond_work)) | ||
295 | kref_put(&ftdi->kref, ftdi_elan_delete); | ||
296 | } | ||
297 | |||
298 | void ftdi_elan_gone_away(struct platform_device *pdev) | ||
299 | { | ||
300 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
301 | ftdi->gone_away += 1; | ||
302 | ftdi_elan_put_kref(ftdi); | ||
303 | } | ||
304 | |||
305 | |||
306 | EXPORT_SYMBOL_GPL(ftdi_elan_gone_away); | ||
307 | void ftdi_release_platform_dev(struct device *dev) | ||
308 | { | ||
309 | dev->parent = NULL; | ||
310 | } | ||
311 | |||
312 | static void ftdi_elan_do_callback(struct usb_ftdi *ftdi, | ||
313 | struct u132_target *target, u8 *buffer, int length); | ||
314 | static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi); | ||
315 | static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi); | ||
316 | static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi); | ||
317 | static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi); | ||
318 | static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi); | ||
319 | static int ftdi_elan_synchronize(struct usb_ftdi *ftdi); | ||
320 | static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi); | ||
321 | static int ftdi_elan_command_engine(struct usb_ftdi *ftdi); | ||
322 | static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi); | ||
323 | static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi) | ||
324 | { | ||
325 | int result; | ||
326 | if (ftdi->platform_dev.dev.parent) | ||
327 | return -EBUSY; | ||
328 | ftdi_elan_get_kref(ftdi); | ||
329 | ftdi->platform_data.potpg = 100; | ||
330 | ftdi->platform_data.reset = NULL; | ||
331 | ftdi->platform_dev.id = ftdi->sequence_num; | ||
332 | ftdi->platform_dev.resource = ftdi->resources; | ||
333 | ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources); | ||
334 | ftdi->platform_dev.dev.platform_data = &ftdi->platform_data; | ||
335 | ftdi->platform_dev.dev.parent = NULL; | ||
336 | ftdi->platform_dev.dev.release = ftdi_release_platform_dev; | ||
337 | ftdi->platform_dev.dev.dma_mask = NULL; | ||
338 | snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd"); | ||
339 | ftdi->platform_dev.name = ftdi->device_name; | ||
340 | dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd"); | ||
341 | request_module("u132_hcd"); | ||
342 | dev_info(&ftdi->udev->dev, "registering '%s'\n", | ||
343 | ftdi->platform_dev.name); | ||
344 | result = platform_device_register(&ftdi->platform_dev); | ||
345 | return result; | ||
346 | } | ||
347 | |||
348 | static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi) | ||
349 | { | ||
350 | down(&ftdi->u132_lock); | ||
351 | while (ftdi->respond_next > ftdi->respond_head) { | ||
352 | struct u132_respond *respond = &ftdi->respond[RESPOND_MASK & | ||
353 | ftdi->respond_head++]; | ||
354 | *respond->result = -ESHUTDOWN; | ||
355 | *respond->value = 0; | ||
356 | complete(&respond->wait_completion); | ||
357 | } up(&ftdi->u132_lock); | ||
358 | } | ||
359 | |||
360 | static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi) | ||
361 | { | ||
362 | int ed_number = 4; | ||
363 | down(&ftdi->u132_lock); | ||
364 | while (ed_number-- > 0) { | ||
365 | struct u132_target *target = &ftdi->target[ed_number]; | ||
366 | if (target->active == 1) { | ||
367 | target->condition_code = TD_DEVNOTRESP; | ||
368 | up(&ftdi->u132_lock); | ||
369 | ftdi_elan_do_callback(ftdi, target, NULL, 0); | ||
370 | down(&ftdi->u132_lock); | ||
371 | } | ||
372 | } | ||
373 | ftdi->recieved = 0; | ||
374 | ftdi->expected = 4; | ||
375 | ftdi->ed_found = 0; | ||
376 | up(&ftdi->u132_lock); | ||
377 | } | ||
378 | |||
379 | static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi) | ||
380 | { | ||
381 | int ed_number = 4; | ||
382 | down(&ftdi->u132_lock); | ||
383 | while (ed_number-- > 0) { | ||
384 | struct u132_target *target = &ftdi->target[ed_number]; | ||
385 | target->abandoning = 1; | ||
386 | wait_1:if (target->active == 1) { | ||
387 | int command_size = ftdi->command_next - | ||
388 | ftdi->command_head; | ||
389 | if (command_size < COMMAND_SIZE) { | ||
390 | struct u132_command *command = &ftdi->command[ | ||
391 | COMMAND_MASK & ftdi->command_next]; | ||
392 | command->header = 0x80 | (ed_number << 5) | 0x4; | ||
393 | command->length = 0x00; | ||
394 | command->address = 0x00; | ||
395 | command->width = 0x00; | ||
396 | command->follows = 0; | ||
397 | command->value = 0; | ||
398 | command->buffer = &command->value; | ||
399 | ftdi->command_next += 1; | ||
400 | ftdi_elan_kick_command_queue(ftdi); | ||
401 | } else { | ||
402 | up(&ftdi->u132_lock); | ||
403 | msleep(100); | ||
404 | down(&ftdi->u132_lock); | ||
405 | goto wait_1; | ||
406 | } | ||
407 | } | ||
408 | wait_2:if (target->active == 1) { | ||
409 | int command_size = ftdi->command_next - | ||
410 | ftdi->command_head; | ||
411 | if (command_size < COMMAND_SIZE) { | ||
412 | struct u132_command *command = &ftdi->command[ | ||
413 | COMMAND_MASK & ftdi->command_next]; | ||
414 | command->header = 0x90 | (ed_number << 5); | ||
415 | command->length = 0x00; | ||
416 | command->address = 0x00; | ||
417 | command->width = 0x00; | ||
418 | command->follows = 0; | ||
419 | command->value = 0; | ||
420 | command->buffer = &command->value; | ||
421 | ftdi->command_next += 1; | ||
422 | ftdi_elan_kick_command_queue(ftdi); | ||
423 | } else { | ||
424 | up(&ftdi->u132_lock); | ||
425 | msleep(100); | ||
426 | down(&ftdi->u132_lock); | ||
427 | goto wait_2; | ||
428 | } | ||
429 | } | ||
430 | } | ||
431 | ftdi->recieved = 0; | ||
432 | ftdi->expected = 4; | ||
433 | ftdi->ed_found = 0; | ||
434 | up(&ftdi->u132_lock); | ||
435 | } | ||
436 | |||
437 | static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi) | ||
438 | { | ||
439 | int ed_number = 4; | ||
440 | down(&ftdi->u132_lock); | ||
441 | while (ed_number-- > 0) { | ||
442 | struct u132_target *target = &ftdi->target[ed_number]; | ||
443 | target->abandoning = 1; | ||
444 | wait:if (target->active == 1) { | ||
445 | int command_size = ftdi->command_next - | ||
446 | ftdi->command_head; | ||
447 | if (command_size < COMMAND_SIZE) { | ||
448 | struct u132_command *command = &ftdi->command[ | ||
449 | COMMAND_MASK & ftdi->command_next]; | ||
450 | command->header = 0x80 | (ed_number << 5) | 0x4; | ||
451 | command->length = 0x00; | ||
452 | command->address = 0x00; | ||
453 | command->width = 0x00; | ||
454 | command->follows = 0; | ||
455 | command->value = 0; | ||
456 | command->buffer = &command->value; | ||
457 | ftdi->command_next += 1; | ||
458 | ftdi_elan_kick_command_queue(ftdi); | ||
459 | } else { | ||
460 | up(&ftdi->u132_lock); | ||
461 | msleep(100); | ||
462 | down(&ftdi->u132_lock); | ||
463 | goto wait; | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | ftdi->recieved = 0; | ||
468 | ftdi->expected = 4; | ||
469 | ftdi->ed_found = 0; | ||
470 | up(&ftdi->u132_lock); | ||
471 | } | ||
472 | |||
473 | static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi) | ||
474 | { | ||
475 | ftdi_command_queue_work(ftdi, 0); | ||
476 | return; | ||
477 | } | ||
478 | |||
479 | static void ftdi_elan_command_work(void *data) | ||
480 | { | ||
481 | struct usb_ftdi *ftdi = data; | ||
482 | if (ftdi->disconnected > 0) { | ||
483 | ftdi_elan_put_kref(ftdi); | ||
484 | return; | ||
485 | } else { | ||
486 | int retval = ftdi_elan_command_engine(ftdi); | ||
487 | if (retval == -ESHUTDOWN) { | ||
488 | ftdi->disconnected += 1; | ||
489 | } else if (retval == -ENODEV) { | ||
490 | ftdi->disconnected += 1; | ||
491 | } else if (retval) | ||
492 | dev_err(&ftdi->udev->dev, "command error %d\n", retval); | ||
493 | ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10)); | ||
494 | return; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi) | ||
499 | { | ||
500 | ftdi_respond_queue_work(ftdi, 0); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | static void ftdi_elan_respond_work(void *data) | ||
505 | { | ||
506 | struct usb_ftdi *ftdi = data; | ||
507 | if (ftdi->disconnected > 0) { | ||
508 | ftdi_elan_put_kref(ftdi); | ||
509 | return; | ||
510 | } else { | ||
511 | int retval = ftdi_elan_respond_engine(ftdi); | ||
512 | if (retval == 0) { | ||
513 | } else if (retval == -ESHUTDOWN) { | ||
514 | ftdi->disconnected += 1; | ||
515 | } else if (retval == -ENODEV) { | ||
516 | ftdi->disconnected += 1; | ||
517 | } else if (retval == -ENODEV) { | ||
518 | ftdi->disconnected += 1; | ||
519 | } else if (retval == -EILSEQ) { | ||
520 | ftdi->disconnected += 1; | ||
521 | } else { | ||
522 | ftdi->disconnected += 1; | ||
523 | dev_err(&ftdi->udev->dev, "respond error %d\n", retval); | ||
524 | } | ||
525 | if (ftdi->disconnected > 0) { | ||
526 | ftdi_elan_abandon_completions(ftdi); | ||
527 | ftdi_elan_abandon_targets(ftdi); | ||
528 | } | ||
529 | ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10)); | ||
530 | return; | ||
531 | } | ||
532 | } | ||
533 | |||
534 | |||
535 | /* | ||
536 | * the sw_lock is initially held and will be freed | ||
537 | * after the FTDI has been synchronized | ||
538 | * | ||
539 | */ | ||
540 | static void ftdi_elan_status_work(void *data) | ||
541 | { | ||
542 | struct usb_ftdi *ftdi = data; | ||
543 | int work_delay_in_msec = 0; | ||
544 | if (ftdi->disconnected > 0) { | ||
545 | ftdi_elan_put_kref(ftdi); | ||
546 | return; | ||
547 | } else if (ftdi->synchronized == 0) { | ||
548 | down(&ftdi->sw_lock); | ||
549 | if (ftdi_elan_synchronize(ftdi) == 0) { | ||
550 | ftdi->synchronized = 1; | ||
551 | ftdi_command_queue_work(ftdi, 1); | ||
552 | ftdi_respond_queue_work(ftdi, 1); | ||
553 | up(&ftdi->sw_lock); | ||
554 | work_delay_in_msec = 100; | ||
555 | } else { | ||
556 | dev_err(&ftdi->udev->dev, "synchronize failed\n"); | ||
557 | up(&ftdi->sw_lock); | ||
558 | work_delay_in_msec = 10 *1000; | ||
559 | } | ||
560 | } else if (ftdi->stuck_status > 0) { | ||
561 | if (ftdi_elan_stuck_waiting(ftdi) == 0) { | ||
562 | ftdi->stuck_status = 0; | ||
563 | ftdi->synchronized = 0; | ||
564 | } else if ((ftdi->stuck_status++ % 60) == 1) { | ||
565 | dev_err(&ftdi->udev->dev, "WRONG type of card inserted " | ||
566 | "- please remove\n"); | ||
567 | } else | ||
568 | dev_err(&ftdi->udev->dev, "WRONG type of card inserted " | ||
569 | "- checked %d times\n", ftdi->stuck_status); | ||
570 | work_delay_in_msec = 100; | ||
571 | } else if (ftdi->enumerated == 0) { | ||
572 | if (ftdi_elan_enumeratePCI(ftdi) == 0) { | ||
573 | ftdi->enumerated = 1; | ||
574 | work_delay_in_msec = 250; | ||
575 | } else | ||
576 | work_delay_in_msec = 1000; | ||
577 | } else if (ftdi->initialized == 0) { | ||
578 | if (ftdi_elan_setupOHCI(ftdi) == 0) { | ||
579 | ftdi->initialized = 1; | ||
580 | work_delay_in_msec = 500; | ||
581 | } else { | ||
582 | dev_err(&ftdi->udev->dev, "initialized failed - trying " | ||
583 | "again in 10 seconds\n"); | ||
584 | work_delay_in_msec = 10 *1000; | ||
585 | } | ||
586 | } else if (ftdi->registered == 0) { | ||
587 | work_delay_in_msec = 10; | ||
588 | if (ftdi_elan_hcd_init(ftdi) == 0) { | ||
589 | ftdi->registered = 1; | ||
590 | } else | ||
591 | dev_err(&ftdi->udev->dev, "register failed\n"); | ||
592 | work_delay_in_msec = 250; | ||
593 | } else { | ||
594 | if (ftdi_elan_checkingPCI(ftdi) == 0) { | ||
595 | work_delay_in_msec = 250; | ||
596 | } else if (ftdi->controlreg & 0x00400000) { | ||
597 | if (ftdi->gone_away > 0) { | ||
598 | dev_err(&ftdi->udev->dev, "PCI device eject con" | ||
599 | "firmed platform_dev.dev.parent=%p plat" | ||
600 | "form_dev.dev=%p\n", | ||
601 | ftdi->platform_dev.dev.parent, | ||
602 | &ftdi->platform_dev.dev); | ||
603 | platform_device_unregister(&ftdi->platform_dev); | ||
604 | ftdi->platform_dev.dev.parent = NULL; | ||
605 | ftdi->registered = 0; | ||
606 | ftdi->enumerated = 0; | ||
607 | ftdi->card_ejected = 0; | ||
608 | ftdi->initialized = 0; | ||
609 | ftdi->gone_away = 0; | ||
610 | } else | ||
611 | ftdi_elan_flush_targets(ftdi); | ||
612 | work_delay_in_msec = 250; | ||
613 | } else { | ||
614 | dev_err(&ftdi->udev->dev, "PCI device has disappeared\n" | ||
615 | ); | ||
616 | ftdi_elan_cancel_targets(ftdi); | ||
617 | work_delay_in_msec = 500; | ||
618 | ftdi->enumerated = 0; | ||
619 | ftdi->initialized = 0; | ||
620 | } | ||
621 | } | ||
622 | if (ftdi->disconnected > 0) { | ||
623 | ftdi_elan_put_kref(ftdi); | ||
624 | return; | ||
625 | } else { | ||
626 | ftdi_status_requeue_work(ftdi, | ||
627 | msecs_to_jiffies(work_delay_in_msec)); | ||
628 | return; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | |||
633 | /* | ||
634 | * file_operations for the jtag interface | ||
635 | * | ||
636 | * the usage count for the device is incremented on open() | ||
637 | * and decremented on release() | ||
638 | */ | ||
639 | static int ftdi_elan_open(struct inode *inode, struct file *file) | ||
640 | { | ||
641 | int subminor = iminor(inode); | ||
642 | struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver, | ||
643 | subminor); | ||
644 | if (!interface) { | ||
645 | printk(KERN_ERR "can't find device for minor %d\n", subminor); | ||
646 | return -ENODEV; | ||
647 | } else { | ||
648 | struct usb_ftdi *ftdi = usb_get_intfdata(interface); | ||
649 | if (!ftdi) { | ||
650 | return -ENODEV; | ||
651 | } else { | ||
652 | if (down_interruptible(&ftdi->sw_lock)) { | ||
653 | return -EINTR; | ||
654 | } else { | ||
655 | ftdi_elan_get_kref(ftdi); | ||
656 | file->private_data = ftdi; | ||
657 | return 0; | ||
658 | } | ||
659 | } | ||
660 | } | ||
661 | } | ||
662 | |||
663 | static int ftdi_elan_release(struct inode *inode, struct file *file) | ||
664 | { | ||
665 | struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; | ||
666 | if (ftdi == NULL) | ||
667 | return -ENODEV; | ||
668 | up(&ftdi->sw_lock); /* decrement the count on our device */ | ||
669 | ftdi_elan_put_kref(ftdi); | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | |||
674 | #define FTDI_ELAN_IOC_MAGIC 0xA1 | ||
675 | #define FTDI_ELAN_IOCDEBUG _IOC(_IOC_WRITE, FTDI_ELAN_IOC_MAGIC, 1, 132) | ||
676 | static int ftdi_elan_ioctl(struct inode *inode, struct file *file, | ||
677 | unsigned int cmd, unsigned long arg) | ||
678 | { | ||
679 | switch (cmd) { | ||
680 | case FTDI_ELAN_IOCDEBUG:{ | ||
681 | char line[132]; | ||
682 | int size = strncpy_from_user(line, | ||
683 | (const char __user *)arg, sizeof(line)); | ||
684 | if (size < 0) { | ||
685 | return -EINVAL; | ||
686 | } else { | ||
687 | printk(KERN_ERR "TODO: ioctl %s\n", line); | ||
688 | return 0; | ||
689 | } | ||
690 | } | ||
691 | default: | ||
692 | return -EFAULT; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | |||
697 | /* | ||
698 | * | ||
699 | * blocking bulk reads are used to get data from the device | ||
700 | * | ||
701 | */ | ||
702 | static ssize_t ftdi_elan_read(struct file *file, char __user *buffer, | ||
703 | size_t count, loff_t *ppos) | ||
704 | { | ||
705 | char data[30 *3 + 4]; | ||
706 | char *d = data; | ||
707 | int m = (sizeof(data) - 1) / 3; | ||
708 | int bytes_read = 0; | ||
709 | int retry_on_empty = 10; | ||
710 | int retry_on_timeout = 5; | ||
711 | struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; | ||
712 | if (ftdi->disconnected > 0) { | ||
713 | return -ENODEV; | ||
714 | } | ||
715 | data[0] = 0; | ||
716 | have:if (ftdi->bulk_in_left > 0) { | ||
717 | if (count-- > 0) { | ||
718 | char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer; | ||
719 | ftdi->bulk_in_left -= 1; | ||
720 | if (bytes_read < m) { | ||
721 | d += sprintf(d, " %02X", 0x000000FF & *p); | ||
722 | } else if (bytes_read > m) { | ||
723 | } else | ||
724 | d += sprintf(d, " .."); | ||
725 | if (copy_to_user(buffer++, p, 1)) { | ||
726 | return -EFAULT; | ||
727 | } else { | ||
728 | bytes_read += 1; | ||
729 | goto have; | ||
730 | } | ||
731 | } else | ||
732 | return bytes_read; | ||
733 | } | ||
734 | more:if (count > 0) { | ||
735 | int packet_bytes = 0; | ||
736 | int retval = usb_bulk_msg(ftdi->udev, | ||
737 | usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), | ||
738 | ftdi->bulk_in_buffer, ftdi->bulk_in_size, | ||
739 | &packet_bytes, msecs_to_jiffies(50)); | ||
740 | if (packet_bytes > 2) { | ||
741 | ftdi->bulk_in_left = packet_bytes - 2; | ||
742 | ftdi->bulk_in_last = 1; | ||
743 | goto have; | ||
744 | } else if (retval == -ETIMEDOUT) { | ||
745 | if (retry_on_timeout-- > 0) { | ||
746 | goto more; | ||
747 | } else if (bytes_read > 0) { | ||
748 | return bytes_read; | ||
749 | } else | ||
750 | return retval; | ||
751 | } else if (retval == 0) { | ||
752 | if (retry_on_empty-- > 0) { | ||
753 | goto more; | ||
754 | } else | ||
755 | return bytes_read; | ||
756 | } else | ||
757 | return retval; | ||
758 | } else | ||
759 | return bytes_read; | ||
760 | } | ||
761 | |||
762 | static void ftdi_elan_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | ||
763 | { | ||
764 | struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context; | ||
765 | if (urb->status && !(urb->status == -ENOENT || urb->status == | ||
766 | -ECONNRESET || urb->status == -ESHUTDOWN)) { | ||
767 | dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %" | ||
768 | "d\n", urb, urb->status); | ||
769 | } | ||
770 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
771 | urb->transfer_buffer, urb->transfer_dma); | ||
772 | } | ||
773 | |||
774 | static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi, | ||
775 | char *buf, int command_size, int total_size) | ||
776 | { | ||
777 | int ed_commands = 0; | ||
778 | int b = 0; | ||
779 | int I = command_size; | ||
780 | int i = ftdi->command_head; | ||
781 | while (I-- > 0) { | ||
782 | struct u132_command *command = &ftdi->command[COMMAND_MASK & | ||
783 | i++]; | ||
784 | int F = command->follows; | ||
785 | u8 *f = command->buffer; | ||
786 | if (command->header & 0x80) { | ||
787 | ed_commands |= 1 << (0x3 & (command->header >> 5)); | ||
788 | } | ||
789 | buf[b++] = command->header; | ||
790 | buf[b++] = (command->length >> 0) & 0x00FF; | ||
791 | buf[b++] = (command->length >> 8) & 0x00FF; | ||
792 | buf[b++] = command->address; | ||
793 | buf[b++] = command->width; | ||
794 | while (F-- > 0) { | ||
795 | buf[b++] = *f++; | ||
796 | } | ||
797 | } | ||
798 | return ed_commands; | ||
799 | } | ||
800 | |||
801 | static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size) | ||
802 | { | ||
803 | int total_size = 0; | ||
804 | int I = command_size; | ||
805 | int i = ftdi->command_head; | ||
806 | while (I-- > 0) { | ||
807 | struct u132_command *command = &ftdi->command[COMMAND_MASK & | ||
808 | i++]; | ||
809 | total_size += 5 + command->follows; | ||
810 | } return total_size; | ||
811 | } | ||
812 | |||
813 | static int ftdi_elan_command_engine(struct usb_ftdi *ftdi) | ||
814 | { | ||
815 | int retval; | ||
816 | char *buf; | ||
817 | int ed_commands; | ||
818 | int total_size; | ||
819 | struct urb *urb; | ||
820 | int command_size = ftdi->command_next - ftdi->command_head; | ||
821 | if (command_size == 0) | ||
822 | return 0; | ||
823 | total_size = ftdi_elan_total_command_size(ftdi, command_size); | ||
824 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
825 | if (!urb) { | ||
826 | dev_err(&ftdi->udev->dev, "could not get a urb to write %d comm" | ||
827 | "ands totaling %d bytes to the Uxxx\n", command_size, | ||
828 | total_size); | ||
829 | return -ENOMEM; | ||
830 | } | ||
831 | buf = usb_buffer_alloc(ftdi->udev, total_size, GFP_KERNEL, | ||
832 | &urb->transfer_dma); | ||
833 | if (!buf) { | ||
834 | dev_err(&ftdi->udev->dev, "could not get a buffer to write %d c" | ||
835 | "ommands totaling %d bytes to the Uxxx\n", command_size, | ||
836 | total_size); | ||
837 | usb_free_urb(urb); | ||
838 | return -ENOMEM; | ||
839 | } | ||
840 | ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf, | ||
841 | command_size, total_size); | ||
842 | usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, | ||
843 | ftdi->bulk_out_endpointAddr), buf, total_size, | ||
844 | ftdi_elan_write_bulk_callback, ftdi); | ||
845 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
846 | if (ed_commands) { | ||
847 | char diag[40 *3 + 4]; | ||
848 | char *d = diag; | ||
849 | int m = total_size; | ||
850 | u8 *c = buf; | ||
851 | int s = (sizeof(diag) - 1) / 3; | ||
852 | diag[0] = 0; | ||
853 | while (s-- > 0 && m-- > 0) { | ||
854 | if (s > 0 || m == 0) { | ||
855 | d += sprintf(d, " %02X", *c++); | ||
856 | } else | ||
857 | d += sprintf(d, " .."); | ||
858 | } | ||
859 | } | ||
860 | retval = usb_submit_urb(urb, GFP_KERNEL); | ||
861 | if (retval) { | ||
862 | dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write " | ||
863 | "%d commands totaling %d bytes to the Uxxx\n", retval, | ||
864 | urb, command_size, total_size); | ||
865 | usb_buffer_free(ftdi->udev, total_size, buf, urb->transfer_dma); | ||
866 | usb_free_urb(urb); | ||
867 | return retval; | ||
868 | } | ||
869 | usb_free_urb(urb); /* release our reference to this urb, | ||
870 | the USB core will eventually free it entirely */ | ||
871 | ftdi->command_head += command_size; | ||
872 | ftdi_elan_kick_respond_queue(ftdi); | ||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static void ftdi_elan_do_callback(struct usb_ftdi *ftdi, | ||
877 | struct u132_target *target, u8 *buffer, int length) | ||
878 | { | ||
879 | struct urb *urb = target->urb; | ||
880 | int halted = target->halted; | ||
881 | int skipped = target->skipped; | ||
882 | int actual = target->actual; | ||
883 | int non_null = target->non_null; | ||
884 | int toggle_bits = target->toggle_bits; | ||
885 | int error_count = target->error_count; | ||
886 | int condition_code = target->condition_code; | ||
887 | int repeat_number = target->repeat_number; | ||
888 | void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int, | ||
889 | int, int, int, int) = target->callback; | ||
890 | target->active -= 1; | ||
891 | target->callback = NULL; | ||
892 | (*callback) (target->endp, urb, buffer, length, toggle_bits, | ||
893 | error_count, condition_code, repeat_number, halted, skipped, | ||
894 | actual, non_null); | ||
895 | } | ||
896 | |||
897 | static char *have_ed_set_response(struct usb_ftdi *ftdi, | ||
898 | struct u132_target *target, u16 ed_length, int ed_number, int ed_type, | ||
899 | char *b) | ||
900 | { | ||
901 | int payload = (ed_length >> 0) & 0x07FF; | ||
902 | down(&ftdi->u132_lock); | ||
903 | target->actual = 0; | ||
904 | target->non_null = (ed_length >> 15) & 0x0001; | ||
905 | target->repeat_number = (ed_length >> 11) & 0x000F; | ||
906 | if (ed_type == 0x02) { | ||
907 | if (payload == 0 || target->abandoning > 0) { | ||
908 | target->abandoning = 0; | ||
909 | up(&ftdi->u132_lock); | ||
910 | ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, | ||
911 | payload); | ||
912 | ftdi->recieved = 0; | ||
913 | ftdi->expected = 4; | ||
914 | ftdi->ed_found = 0; | ||
915 | return ftdi->response; | ||
916 | } else { | ||
917 | ftdi->expected = 4 + payload; | ||
918 | ftdi->ed_found = 1; | ||
919 | up(&ftdi->u132_lock); | ||
920 | return b; | ||
921 | } | ||
922 | } else if (ed_type == 0x03) { | ||
923 | if (payload == 0 || target->abandoning > 0) { | ||
924 | target->abandoning = 0; | ||
925 | up(&ftdi->u132_lock); | ||
926 | ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, | ||
927 | payload); | ||
928 | ftdi->recieved = 0; | ||
929 | ftdi->expected = 4; | ||
930 | ftdi->ed_found = 0; | ||
931 | return ftdi->response; | ||
932 | } else { | ||
933 | ftdi->expected = 4 + payload; | ||
934 | ftdi->ed_found = 1; | ||
935 | up(&ftdi->u132_lock); | ||
936 | return b; | ||
937 | } | ||
938 | } else if (ed_type == 0x01) { | ||
939 | target->abandoning = 0; | ||
940 | up(&ftdi->u132_lock); | ||
941 | ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, | ||
942 | payload); | ||
943 | ftdi->recieved = 0; | ||
944 | ftdi->expected = 4; | ||
945 | ftdi->ed_found = 0; | ||
946 | return ftdi->response; | ||
947 | } else { | ||
948 | target->abandoning = 0; | ||
949 | up(&ftdi->u132_lock); | ||
950 | ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, | ||
951 | payload); | ||
952 | ftdi->recieved = 0; | ||
953 | ftdi->expected = 4; | ||
954 | ftdi->ed_found = 0; | ||
955 | return ftdi->response; | ||
956 | } | ||
957 | } | ||
958 | |||
959 | static char *have_ed_get_response(struct usb_ftdi *ftdi, | ||
960 | struct u132_target *target, u16 ed_length, int ed_number, int ed_type, | ||
961 | char *b) | ||
962 | { | ||
963 | down(&ftdi->u132_lock); | ||
964 | target->condition_code = TD_DEVNOTRESP; | ||
965 | target->actual = (ed_length >> 0) & 0x01FF; | ||
966 | target->non_null = (ed_length >> 15) & 0x0001; | ||
967 | target->repeat_number = (ed_length >> 11) & 0x000F; | ||
968 | up(&ftdi->u132_lock); | ||
969 | if (target->active) | ||
970 | ftdi_elan_do_callback(ftdi, target, NULL, 0); | ||
971 | target->abandoning = 0; | ||
972 | ftdi->recieved = 0; | ||
973 | ftdi->expected = 4; | ||
974 | ftdi->ed_found = 0; | ||
975 | return ftdi->response; | ||
976 | } | ||
977 | |||
978 | |||
979 | /* | ||
980 | * The engine tries to empty the FTDI fifo | ||
981 | * | ||
982 | * all responses found in the fifo data are dispatched thus | ||
983 | * the response buffer can only ever hold a maximum sized | ||
984 | * response from the Uxxx. | ||
985 | * | ||
986 | */ | ||
987 | static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi) | ||
988 | { | ||
989 | u8 *b = ftdi->response + ftdi->recieved; | ||
990 | int bytes_read = 0; | ||
991 | int retry_on_empty = 1; | ||
992 | int retry_on_timeout = 3; | ||
993 | int empty_packets = 0; | ||
994 | read:{ | ||
995 | int packet_bytes = 0; | ||
996 | int retval = usb_bulk_msg(ftdi->udev, | ||
997 | usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), | ||
998 | ftdi->bulk_in_buffer, ftdi->bulk_in_size, | ||
999 | &packet_bytes, msecs_to_jiffies(500)); | ||
1000 | char diag[30 *3 + 4]; | ||
1001 | char *d = diag; | ||
1002 | int m = packet_bytes; | ||
1003 | u8 *c = ftdi->bulk_in_buffer; | ||
1004 | int s = (sizeof(diag) - 1) / 3; | ||
1005 | diag[0] = 0; | ||
1006 | while (s-- > 0 && m-- > 0) { | ||
1007 | if (s > 0 || m == 0) { | ||
1008 | d += sprintf(d, " %02X", *c++); | ||
1009 | } else | ||
1010 | d += sprintf(d, " .."); | ||
1011 | } | ||
1012 | if (packet_bytes > 2) { | ||
1013 | ftdi->bulk_in_left = packet_bytes - 2; | ||
1014 | ftdi->bulk_in_last = 1; | ||
1015 | goto have; | ||
1016 | } else if (retval == -ETIMEDOUT) { | ||
1017 | if (retry_on_timeout-- > 0) { | ||
1018 | dev_err(&ftdi->udev->dev, "TIMED OUT with packe" | ||
1019 | "t_bytes = %d with total %d bytes%s\n", | ||
1020 | packet_bytes, bytes_read, diag); | ||
1021 | goto more; | ||
1022 | } else if (bytes_read > 0) { | ||
1023 | dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n", | ||
1024 | bytes_read, diag); | ||
1025 | return -ENOMEM; | ||
1026 | } else { | ||
1027 | dev_err(&ftdi->udev->dev, "TIMED OUT with packe" | ||
1028 | "t_bytes = %d with total %d bytes%s\n", | ||
1029 | packet_bytes, bytes_read, diag); | ||
1030 | return -ENOMEM; | ||
1031 | } | ||
1032 | } else if (retval == -EILSEQ) { | ||
1033 | dev_err(&ftdi->udev->dev, "error = %d with packet_bytes" | ||
1034 | " = %d with total %d bytes%s\n", retval, | ||
1035 | packet_bytes, bytes_read, diag); | ||
1036 | return retval; | ||
1037 | } else if (retval) { | ||
1038 | dev_err(&ftdi->udev->dev, "error = %d with packet_bytes" | ||
1039 | " = %d with total %d bytes%s\n", retval, | ||
1040 | packet_bytes, bytes_read, diag); | ||
1041 | return retval; | ||
1042 | } else if (packet_bytes == 2) { | ||
1043 | unsigned char s0 = ftdi->bulk_in_buffer[0]; | ||
1044 | unsigned char s1 = ftdi->bulk_in_buffer[1]; | ||
1045 | empty_packets += 1; | ||
1046 | if (s0 == 0x31 && s1 == 0x60) { | ||
1047 | if (retry_on_empty-- > 0) { | ||
1048 | goto more; | ||
1049 | } else | ||
1050 | return 0; | ||
1051 | } else if (s0 == 0x31 && s1 == 0x00) { | ||
1052 | if (retry_on_empty-- > 0) { | ||
1053 | goto more; | ||
1054 | } else | ||
1055 | return 0; | ||
1056 | } else { | ||
1057 | if (retry_on_empty-- > 0) { | ||
1058 | goto more; | ||
1059 | } else | ||
1060 | return 0; | ||
1061 | } | ||
1062 | } else if (packet_bytes == 1) { | ||
1063 | if (retry_on_empty-- > 0) { | ||
1064 | goto more; | ||
1065 | } else | ||
1066 | return 0; | ||
1067 | } else { | ||
1068 | if (retry_on_empty-- > 0) { | ||
1069 | goto more; | ||
1070 | } else | ||
1071 | return 0; | ||
1072 | } | ||
1073 | } | ||
1074 | more:{ | ||
1075 | goto read; | ||
1076 | } | ||
1077 | have:if (ftdi->bulk_in_left > 0) { | ||
1078 | u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last]; | ||
1079 | bytes_read += 1; | ||
1080 | ftdi->bulk_in_left -= 1; | ||
1081 | if (ftdi->recieved == 0 && c == 0xFF) { | ||
1082 | goto have; | ||
1083 | } else | ||
1084 | *b++ = c; | ||
1085 | if (++ftdi->recieved < ftdi->expected) { | ||
1086 | goto have; | ||
1087 | } else if (ftdi->ed_found) { | ||
1088 | int ed_number = (ftdi->response[0] >> 5) & 0x03; | ||
1089 | u16 ed_length = (ftdi->response[2] << 8) | | ||
1090 | ftdi->response[1]; | ||
1091 | struct u132_target *target = &ftdi->target[ed_number]; | ||
1092 | int payload = (ed_length >> 0) & 0x07FF; | ||
1093 | char diag[30 *3 + 4]; | ||
1094 | char *d = diag; | ||
1095 | int m = payload; | ||
1096 | u8 *c = 4 + ftdi->response; | ||
1097 | int s = (sizeof(diag) - 1) / 3; | ||
1098 | diag[0] = 0; | ||
1099 | while (s-- > 0 && m-- > 0) { | ||
1100 | if (s > 0 || m == 0) { | ||
1101 | d += sprintf(d, " %02X", *c++); | ||
1102 | } else | ||
1103 | d += sprintf(d, " .."); | ||
1104 | } | ||
1105 | ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, | ||
1106 | payload); | ||
1107 | ftdi->recieved = 0; | ||
1108 | ftdi->expected = 4; | ||
1109 | ftdi->ed_found = 0; | ||
1110 | b = ftdi->response; | ||
1111 | goto have; | ||
1112 | } else if (ftdi->expected == 8) { | ||
1113 | u8 buscmd; | ||
1114 | int respond_head = ftdi->respond_head++; | ||
1115 | struct u132_respond *respond = &ftdi->respond[ | ||
1116 | RESPOND_MASK & respond_head]; | ||
1117 | u32 data = ftdi->response[7]; | ||
1118 | data <<= 8; | ||
1119 | data |= ftdi->response[6]; | ||
1120 | data <<= 8; | ||
1121 | data |= ftdi->response[5]; | ||
1122 | data <<= 8; | ||
1123 | data |= ftdi->response[4]; | ||
1124 | *respond->value = data; | ||
1125 | *respond->result = 0; | ||
1126 | complete(&respond->wait_completion); | ||
1127 | ftdi->recieved = 0; | ||
1128 | ftdi->expected = 4; | ||
1129 | ftdi->ed_found = 0; | ||
1130 | b = ftdi->response; | ||
1131 | buscmd = (ftdi->response[0] >> 0) & 0x0F; | ||
1132 | if (buscmd == 0x00) { | ||
1133 | } else if (buscmd == 0x02) { | ||
1134 | } else if (buscmd == 0x06) { | ||
1135 | } else if (buscmd == 0x0A) { | ||
1136 | } else | ||
1137 | dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) va" | ||
1138 | "lue = %08X\n", buscmd, data); | ||
1139 | goto have; | ||
1140 | } else { | ||
1141 | if ((ftdi->response[0] & 0x80) == 0x00) { | ||
1142 | ftdi->expected = 8; | ||
1143 | goto have; | ||
1144 | } else { | ||
1145 | int ed_number = (ftdi->response[0] >> 5) & 0x03; | ||
1146 | int ed_type = (ftdi->response[0] >> 0) & 0x03; | ||
1147 | u16 ed_length = (ftdi->response[2] << 8) | | ||
1148 | ftdi->response[1]; | ||
1149 | struct u132_target *target = &ftdi->target[ | ||
1150 | ed_number]; | ||
1151 | target->halted = (ftdi->response[0] >> 3) & | ||
1152 | 0x01; | ||
1153 | target->skipped = (ftdi->response[0] >> 2) & | ||
1154 | 0x01; | ||
1155 | target->toggle_bits = (ftdi->response[3] >> 6) | ||
1156 | & 0x03; | ||
1157 | target->error_count = (ftdi->response[3] >> 4) | ||
1158 | & 0x03; | ||
1159 | target->condition_code = (ftdi->response[ | ||
1160 | 3] >> 0) & 0x0F; | ||
1161 | if ((ftdi->response[0] & 0x10) == 0x00) { | ||
1162 | b = have_ed_set_response(ftdi, target, | ||
1163 | ed_length, ed_number, ed_type, | ||
1164 | b); | ||
1165 | goto have; | ||
1166 | } else { | ||
1167 | b = have_ed_get_response(ftdi, target, | ||
1168 | ed_length, ed_number, ed_type, | ||
1169 | b); | ||
1170 | goto have; | ||
1171 | } | ||
1172 | } | ||
1173 | } | ||
1174 | } else | ||
1175 | goto more; | ||
1176 | } | ||
1177 | |||
1178 | |||
1179 | /* | ||
1180 | * create a urb, and a buffer for it, and copy the data to the urb | ||
1181 | * | ||
1182 | */ | ||
1183 | static ssize_t ftdi_elan_write(struct file *file, | ||
1184 | const char __user *user_buffer, size_t count, | ||
1185 | loff_t *ppos) | ||
1186 | { | ||
1187 | int retval = 0; | ||
1188 | struct urb *urb; | ||
1189 | char *buf; | ||
1190 | char data[30 *3 + 4]; | ||
1191 | char *d = data; | ||
1192 | const char __user *s = user_buffer; | ||
1193 | int m = (sizeof(data) - 1) / 3; | ||
1194 | struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; | ||
1195 | if (ftdi->disconnected > 0) { | ||
1196 | return -ENODEV; | ||
1197 | } | ||
1198 | if (count == 0) { | ||
1199 | goto exit; | ||
1200 | } | ||
1201 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1202 | if (!urb) { | ||
1203 | retval = -ENOMEM; | ||
1204 | goto error_1; | ||
1205 | } | ||
1206 | buf = usb_buffer_alloc(ftdi->udev, count, GFP_KERNEL, | ||
1207 | &urb->transfer_dma); | ||
1208 | if (!buf) { | ||
1209 | retval = -ENOMEM; | ||
1210 | goto error_2; | ||
1211 | } | ||
1212 | if (copy_from_user(buf, user_buffer, count)) { | ||
1213 | retval = -EFAULT; | ||
1214 | goto error_3; | ||
1215 | } | ||
1216 | usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, | ||
1217 | ftdi->bulk_out_endpointAddr), buf, count, | ||
1218 | ftdi_elan_write_bulk_callback, ftdi); | ||
1219 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
1220 | retval = usb_submit_urb(urb, GFP_KERNEL); | ||
1221 | if (retval) { | ||
1222 | dev_err(&ftdi->udev->dev, "failed submitting write urb, error %" | ||
1223 | "d\n", retval); | ||
1224 | goto error_4; | ||
1225 | } | ||
1226 | usb_free_urb(urb); | ||
1227 | exit:; | ||
1228 | if (count > m) { | ||
1229 | int I = m - 1; | ||
1230 | while (I-- > 0) { | ||
1231 | d += sprintf(d, " %02X", 0x000000FF & *s++); | ||
1232 | } | ||
1233 | d += sprintf(d, " .."); | ||
1234 | } else { | ||
1235 | int I = count; | ||
1236 | while (I-- > 0) { | ||
1237 | d += sprintf(d, " %02X", 0x000000FF & *s++); | ||
1238 | } | ||
1239 | } | ||
1240 | return count; | ||
1241 | error_4: error_3:usb_buffer_free(ftdi->udev, count, buf, | ||
1242 | urb->transfer_dma); | ||
1243 | error_2:usb_free_urb(urb); | ||
1244 | error_1:return retval; | ||
1245 | } | ||
1246 | |||
1247 | static struct file_operations ftdi_elan_fops = { | ||
1248 | .owner = THIS_MODULE, | ||
1249 | .llseek = no_llseek, | ||
1250 | .ioctl = ftdi_elan_ioctl, | ||
1251 | .read = ftdi_elan_read, | ||
1252 | .write = ftdi_elan_write, | ||
1253 | .open = ftdi_elan_open, | ||
1254 | .release = ftdi_elan_release, | ||
1255 | }; | ||
1256 | |||
1257 | /* | ||
1258 | * usb class driver info in order to get a minor number from the usb core, | ||
1259 | * and to have the device registered with the driver core | ||
1260 | */ | ||
1261 | static struct usb_class_driver ftdi_elan_jtag_class = { | ||
1262 | .name = "ftdi-%d-jtag", | ||
1263 | .fops = &ftdi_elan_fops, | ||
1264 | .minor_base = USB_FTDI_ELAN_MINOR_BASE, | ||
1265 | }; | ||
1266 | |||
1267 | /* | ||
1268 | * the following definitions are for the | ||
1269 | * ELAN FPGA state machgine processor that | ||
1270 | * lies on the other side of the FTDI chip | ||
1271 | */ | ||
1272 | #define cPCIu132rd 0x0 | ||
1273 | #define cPCIu132wr 0x1 | ||
1274 | #define cPCIiord 0x2 | ||
1275 | #define cPCIiowr 0x3 | ||
1276 | #define cPCImemrd 0x6 | ||
1277 | #define cPCImemwr 0x7 | ||
1278 | #define cPCIcfgrd 0xA | ||
1279 | #define cPCIcfgwr 0xB | ||
1280 | #define cPCInull 0xF | ||
1281 | #define cU132cmd_status 0x0 | ||
1282 | #define cU132flash 0x1 | ||
1283 | #define cPIDsetup 0x0 | ||
1284 | #define cPIDout 0x1 | ||
1285 | #define cPIDin 0x2 | ||
1286 | #define cPIDinonce 0x3 | ||
1287 | #define cCCnoerror 0x0 | ||
1288 | #define cCCcrc 0x1 | ||
1289 | #define cCCbitstuff 0x2 | ||
1290 | #define cCCtoggle 0x3 | ||
1291 | #define cCCstall 0x4 | ||
1292 | #define cCCnoresp 0x5 | ||
1293 | #define cCCbadpid1 0x6 | ||
1294 | #define cCCbadpid2 0x7 | ||
1295 | #define cCCdataoverrun 0x8 | ||
1296 | #define cCCdataunderrun 0x9 | ||
1297 | #define cCCbuffoverrun 0xC | ||
1298 | #define cCCbuffunderrun 0xD | ||
1299 | #define cCCnotaccessed 0xF | ||
1300 | static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data) | ||
1301 | { | ||
1302 | wait:if (ftdi->disconnected > 0) { | ||
1303 | return -ENODEV; | ||
1304 | } else { | ||
1305 | int command_size; | ||
1306 | down(&ftdi->u132_lock); | ||
1307 | command_size = ftdi->command_next - ftdi->command_head; | ||
1308 | if (command_size < COMMAND_SIZE) { | ||
1309 | struct u132_command *command = &ftdi->command[ | ||
1310 | COMMAND_MASK & ftdi->command_next]; | ||
1311 | command->header = 0x00 | cPCIu132wr; | ||
1312 | command->length = 0x04; | ||
1313 | command->address = 0x00; | ||
1314 | command->width = 0x00; | ||
1315 | command->follows = 4; | ||
1316 | command->value = data; | ||
1317 | command->buffer = &command->value; | ||
1318 | ftdi->command_next += 1; | ||
1319 | ftdi_elan_kick_command_queue(ftdi); | ||
1320 | up(&ftdi->u132_lock); | ||
1321 | return 0; | ||
1322 | } else { | ||
1323 | up(&ftdi->u132_lock); | ||
1324 | msleep(100); | ||
1325 | goto wait; | ||
1326 | } | ||
1327 | } | ||
1328 | } | ||
1329 | |||
1330 | static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset, | ||
1331 | u8 width, u32 data) | ||
1332 | { | ||
1333 | u8 addressofs = config_offset / 4; | ||
1334 | wait:if (ftdi->disconnected > 0) { | ||
1335 | return -ENODEV; | ||
1336 | } else { | ||
1337 | int command_size; | ||
1338 | down(&ftdi->u132_lock); | ||
1339 | command_size = ftdi->command_next - ftdi->command_head; | ||
1340 | if (command_size < COMMAND_SIZE) { | ||
1341 | struct u132_command *command = &ftdi->command[ | ||
1342 | COMMAND_MASK & ftdi->command_next]; | ||
1343 | command->header = 0x00 | (cPCIcfgwr & 0x0F); | ||
1344 | command->length = 0x04; | ||
1345 | command->address = addressofs; | ||
1346 | command->width = 0x00 | (width & 0x0F); | ||
1347 | command->follows = 4; | ||
1348 | command->value = data; | ||
1349 | command->buffer = &command->value; | ||
1350 | ftdi->command_next += 1; | ||
1351 | ftdi_elan_kick_command_queue(ftdi); | ||
1352 | up(&ftdi->u132_lock); | ||
1353 | return 0; | ||
1354 | } else { | ||
1355 | up(&ftdi->u132_lock); | ||
1356 | msleep(100); | ||
1357 | goto wait; | ||
1358 | } | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset, | ||
1363 | u8 width, u32 data) | ||
1364 | { | ||
1365 | u8 addressofs = mem_offset / 4; | ||
1366 | wait:if (ftdi->disconnected > 0) { | ||
1367 | return -ENODEV; | ||
1368 | } else { | ||
1369 | int command_size; | ||
1370 | down(&ftdi->u132_lock); | ||
1371 | command_size = ftdi->command_next - ftdi->command_head; | ||
1372 | if (command_size < COMMAND_SIZE) { | ||
1373 | struct u132_command *command = &ftdi->command[ | ||
1374 | COMMAND_MASK & ftdi->command_next]; | ||
1375 | command->header = 0x00 | (cPCImemwr & 0x0F); | ||
1376 | command->length = 0x04; | ||
1377 | command->address = addressofs; | ||
1378 | command->width = 0x00 | (width & 0x0F); | ||
1379 | command->follows = 4; | ||
1380 | command->value = data; | ||
1381 | command->buffer = &command->value; | ||
1382 | ftdi->command_next += 1; | ||
1383 | ftdi_elan_kick_command_queue(ftdi); | ||
1384 | up(&ftdi->u132_lock); | ||
1385 | return 0; | ||
1386 | } else { | ||
1387 | up(&ftdi->u132_lock); | ||
1388 | msleep(100); | ||
1389 | goto wait; | ||
1390 | } | ||
1391 | } | ||
1392 | } | ||
1393 | |||
1394 | int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset, | ||
1395 | u8 width, u32 data) | ||
1396 | { | ||
1397 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1398 | return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data); | ||
1399 | } | ||
1400 | |||
1401 | |||
1402 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_write_pcimem); | ||
1403 | static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data) | ||
1404 | { | ||
1405 | wait:if (ftdi->disconnected > 0) { | ||
1406 | return -ENODEV; | ||
1407 | } else { | ||
1408 | int command_size; | ||
1409 | int respond_size; | ||
1410 | down(&ftdi->u132_lock); | ||
1411 | command_size = ftdi->command_next - ftdi->command_head; | ||
1412 | respond_size = ftdi->respond_next - ftdi->respond_head; | ||
1413 | if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) | ||
1414 | { | ||
1415 | struct u132_command *command = &ftdi->command[ | ||
1416 | COMMAND_MASK & ftdi->command_next]; | ||
1417 | struct u132_respond *respond = &ftdi->respond[ | ||
1418 | RESPOND_MASK & ftdi->respond_next]; | ||
1419 | int result = -ENODEV; | ||
1420 | respond->result = &result; | ||
1421 | respond->header = command->header = 0x00 | cPCIu132rd; | ||
1422 | command->length = 0x04; | ||
1423 | respond->address = command->address = cU132cmd_status; | ||
1424 | command->width = 0x00; | ||
1425 | command->follows = 0; | ||
1426 | command->value = 0; | ||
1427 | command->buffer = NULL; | ||
1428 | respond->value = data; | ||
1429 | init_completion(&respond->wait_completion); | ||
1430 | ftdi->command_next += 1; | ||
1431 | ftdi->respond_next += 1; | ||
1432 | ftdi_elan_kick_command_queue(ftdi); | ||
1433 | up(&ftdi->u132_lock); | ||
1434 | wait_for_completion(&respond->wait_completion); | ||
1435 | return result; | ||
1436 | } else { | ||
1437 | up(&ftdi->u132_lock); | ||
1438 | msleep(100); | ||
1439 | goto wait; | ||
1440 | } | ||
1441 | } | ||
1442 | } | ||
1443 | |||
1444 | int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data) | ||
1445 | { | ||
1446 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1447 | return ftdi_elan_read_reg(ftdi, data); | ||
1448 | } | ||
1449 | |||
1450 | |||
1451 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg); | ||
1452 | static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset, | ||
1453 | u8 width, u32 *data) | ||
1454 | { | ||
1455 | u8 addressofs = config_offset / 4; | ||
1456 | wait:if (ftdi->disconnected > 0) { | ||
1457 | return -ENODEV; | ||
1458 | } else { | ||
1459 | int command_size; | ||
1460 | int respond_size; | ||
1461 | down(&ftdi->u132_lock); | ||
1462 | command_size = ftdi->command_next - ftdi->command_head; | ||
1463 | respond_size = ftdi->respond_next - ftdi->respond_head; | ||
1464 | if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) | ||
1465 | { | ||
1466 | struct u132_command *command = &ftdi->command[ | ||
1467 | COMMAND_MASK & ftdi->command_next]; | ||
1468 | struct u132_respond *respond = &ftdi->respond[ | ||
1469 | RESPOND_MASK & ftdi->respond_next]; | ||
1470 | int result = -ENODEV; | ||
1471 | respond->result = &result; | ||
1472 | respond->header = command->header = 0x00 | (cPCIcfgrd & | ||
1473 | 0x0F); | ||
1474 | command->length = 0x04; | ||
1475 | respond->address = command->address = addressofs; | ||
1476 | command->width = 0x00 | (width & 0x0F); | ||
1477 | command->follows = 0; | ||
1478 | command->value = 0; | ||
1479 | command->buffer = NULL; | ||
1480 | respond->value = data; | ||
1481 | init_completion(&respond->wait_completion); | ||
1482 | ftdi->command_next += 1; | ||
1483 | ftdi->respond_next += 1; | ||
1484 | ftdi_elan_kick_command_queue(ftdi); | ||
1485 | up(&ftdi->u132_lock); | ||
1486 | wait_for_completion(&respond->wait_completion); | ||
1487 | return result; | ||
1488 | } else { | ||
1489 | up(&ftdi->u132_lock); | ||
1490 | msleep(100); | ||
1491 | goto wait; | ||
1492 | } | ||
1493 | } | ||
1494 | } | ||
1495 | |||
1496 | static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset, | ||
1497 | u8 width, u32 *data) | ||
1498 | { | ||
1499 | u8 addressofs = mem_offset / 4; | ||
1500 | wait:if (ftdi->disconnected > 0) { | ||
1501 | return -ENODEV; | ||
1502 | } else { | ||
1503 | int command_size; | ||
1504 | int respond_size; | ||
1505 | down(&ftdi->u132_lock); | ||
1506 | command_size = ftdi->command_next - ftdi->command_head; | ||
1507 | respond_size = ftdi->respond_next - ftdi->respond_head; | ||
1508 | if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE) | ||
1509 | { | ||
1510 | struct u132_command *command = &ftdi->command[ | ||
1511 | COMMAND_MASK & ftdi->command_next]; | ||
1512 | struct u132_respond *respond = &ftdi->respond[ | ||
1513 | RESPOND_MASK & ftdi->respond_next]; | ||
1514 | int result = -ENODEV; | ||
1515 | respond->result = &result; | ||
1516 | respond->header = command->header = 0x00 | (cPCImemrd & | ||
1517 | 0x0F); | ||
1518 | command->length = 0x04; | ||
1519 | respond->address = command->address = addressofs; | ||
1520 | command->width = 0x00 | (width & 0x0F); | ||
1521 | command->follows = 0; | ||
1522 | command->value = 0; | ||
1523 | command->buffer = NULL; | ||
1524 | respond->value = data; | ||
1525 | init_completion(&respond->wait_completion); | ||
1526 | ftdi->command_next += 1; | ||
1527 | ftdi->respond_next += 1; | ||
1528 | ftdi_elan_kick_command_queue(ftdi); | ||
1529 | up(&ftdi->u132_lock); | ||
1530 | wait_for_completion(&respond->wait_completion); | ||
1531 | return result; | ||
1532 | } else { | ||
1533 | up(&ftdi->u132_lock); | ||
1534 | msleep(100); | ||
1535 | goto wait; | ||
1536 | } | ||
1537 | } | ||
1538 | } | ||
1539 | |||
1540 | int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset, | ||
1541 | u8 width, u32 *data) | ||
1542 | { | ||
1543 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1544 | if (ftdi->initialized == 0) { | ||
1545 | return -ENODEV; | ||
1546 | } else | ||
1547 | return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data); | ||
1548 | } | ||
1549 | |||
1550 | |||
1551 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_pcimem); | ||
1552 | static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number, | ||
1553 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1554 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1555 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1556 | int halted, int skipped, int actual, int non_null)) | ||
1557 | { | ||
1558 | u8 ed = ed_number - 1; | ||
1559 | wait:if (ftdi->disconnected > 0) { | ||
1560 | return -ENODEV; | ||
1561 | } else if (ftdi->initialized == 0) { | ||
1562 | return -ENODEV; | ||
1563 | } else { | ||
1564 | int command_size; | ||
1565 | down(&ftdi->u132_lock); | ||
1566 | command_size = ftdi->command_next - ftdi->command_head; | ||
1567 | if (command_size < COMMAND_SIZE) { | ||
1568 | struct u132_target *target = &ftdi->target[ed]; | ||
1569 | struct u132_command *command = &ftdi->command[ | ||
1570 | COMMAND_MASK & ftdi->command_next]; | ||
1571 | command->header = 0x80 | (ed << 5); | ||
1572 | command->length = 0x8007; | ||
1573 | command->address = (toggle_bits << 6) | (ep_number << 2) | ||
1574 | | (address << 0); | ||
1575 | command->width = usb_maxpacket(urb->dev, urb->pipe, | ||
1576 | usb_pipeout(urb->pipe)); | ||
1577 | command->follows = 8; | ||
1578 | command->value = 0; | ||
1579 | command->buffer = urb->setup_packet; | ||
1580 | target->callback = callback; | ||
1581 | target->endp = endp; | ||
1582 | target->urb = urb; | ||
1583 | target->active = 1; | ||
1584 | ftdi->command_next += 1; | ||
1585 | ftdi_elan_kick_command_queue(ftdi); | ||
1586 | up(&ftdi->u132_lock); | ||
1587 | return 0; | ||
1588 | } else { | ||
1589 | up(&ftdi->u132_lock); | ||
1590 | msleep(100); | ||
1591 | goto wait; | ||
1592 | } | ||
1593 | } | ||
1594 | } | ||
1595 | |||
1596 | int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number, | ||
1597 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1598 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1599 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1600 | int halted, int skipped, int actual, int non_null)) | ||
1601 | { | ||
1602 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1603 | return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address, | ||
1604 | ep_number, toggle_bits, callback); | ||
1605 | } | ||
1606 | |||
1607 | |||
1608 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_setup); | ||
1609 | static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number, | ||
1610 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1611 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1612 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1613 | int halted, int skipped, int actual, int non_null)) | ||
1614 | { | ||
1615 | u8 ed = ed_number - 1; | ||
1616 | wait:if (ftdi->disconnected > 0) { | ||
1617 | return -ENODEV; | ||
1618 | } else if (ftdi->initialized == 0) { | ||
1619 | return -ENODEV; | ||
1620 | } else { | ||
1621 | int command_size; | ||
1622 | down(&ftdi->u132_lock); | ||
1623 | command_size = ftdi->command_next - ftdi->command_head; | ||
1624 | if (command_size < COMMAND_SIZE) { | ||
1625 | struct u132_target *target = &ftdi->target[ed]; | ||
1626 | struct u132_command *command = &ftdi->command[ | ||
1627 | COMMAND_MASK & ftdi->command_next]; | ||
1628 | int remaining_length = urb->transfer_buffer_length - | ||
1629 | urb->actual_length; | ||
1630 | command->header = 0x82 | (ed << 5); | ||
1631 | if (remaining_length == 0) { | ||
1632 | command->length = 0x0000; | ||
1633 | } else if (remaining_length > 1024) { | ||
1634 | command->length = 0x8000 | 1023; | ||
1635 | } else | ||
1636 | command->length = 0x8000 | (remaining_length - | ||
1637 | 1); | ||
1638 | command->address = (toggle_bits << 6) | (ep_number << 2) | ||
1639 | | (address << 0); | ||
1640 | command->width = usb_maxpacket(urb->dev, urb->pipe, | ||
1641 | usb_pipeout(urb->pipe)); | ||
1642 | command->follows = 0; | ||
1643 | command->value = 0; | ||
1644 | command->buffer = NULL; | ||
1645 | target->callback = callback; | ||
1646 | target->endp = endp; | ||
1647 | target->urb = urb; | ||
1648 | target->active = 1; | ||
1649 | ftdi->command_next += 1; | ||
1650 | ftdi_elan_kick_command_queue(ftdi); | ||
1651 | up(&ftdi->u132_lock); | ||
1652 | return 0; | ||
1653 | } else { | ||
1654 | up(&ftdi->u132_lock); | ||
1655 | msleep(100); | ||
1656 | goto wait; | ||
1657 | } | ||
1658 | } | ||
1659 | } | ||
1660 | |||
1661 | int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number, | ||
1662 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1663 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1664 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1665 | int halted, int skipped, int actual, int non_null)) | ||
1666 | { | ||
1667 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1668 | return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address, | ||
1669 | ep_number, toggle_bits, callback); | ||
1670 | } | ||
1671 | |||
1672 | |||
1673 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_input); | ||
1674 | static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number, | ||
1675 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1676 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1677 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1678 | int halted, int skipped, int actual, int non_null)) | ||
1679 | { | ||
1680 | u8 ed = ed_number - 1; | ||
1681 | wait:if (ftdi->disconnected > 0) { | ||
1682 | return -ENODEV; | ||
1683 | } else if (ftdi->initialized == 0) { | ||
1684 | return -ENODEV; | ||
1685 | } else { | ||
1686 | int command_size; | ||
1687 | down(&ftdi->u132_lock); | ||
1688 | command_size = ftdi->command_next - ftdi->command_head; | ||
1689 | if (command_size < COMMAND_SIZE) { | ||
1690 | struct u132_target *target = &ftdi->target[ed]; | ||
1691 | struct u132_command *command = &ftdi->command[ | ||
1692 | COMMAND_MASK & ftdi->command_next]; | ||
1693 | command->header = 0x81 | (ed << 5); | ||
1694 | command->length = 0x0000; | ||
1695 | command->address = (toggle_bits << 6) | (ep_number << 2) | ||
1696 | | (address << 0); | ||
1697 | command->width = usb_maxpacket(urb->dev, urb->pipe, | ||
1698 | usb_pipeout(urb->pipe)); | ||
1699 | command->follows = 0; | ||
1700 | command->value = 0; | ||
1701 | command->buffer = NULL; | ||
1702 | target->callback = callback; | ||
1703 | target->endp = endp; | ||
1704 | target->urb = urb; | ||
1705 | target->active = 1; | ||
1706 | ftdi->command_next += 1; | ||
1707 | ftdi_elan_kick_command_queue(ftdi); | ||
1708 | up(&ftdi->u132_lock); | ||
1709 | return 0; | ||
1710 | } else { | ||
1711 | up(&ftdi->u132_lock); | ||
1712 | msleep(100); | ||
1713 | goto wait; | ||
1714 | } | ||
1715 | } | ||
1716 | } | ||
1717 | |||
1718 | int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number, | ||
1719 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1720 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1721 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1722 | int halted, int skipped, int actual, int non_null)) | ||
1723 | { | ||
1724 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1725 | return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address, | ||
1726 | ep_number, toggle_bits, callback); | ||
1727 | } | ||
1728 | |||
1729 | |||
1730 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_empty); | ||
1731 | static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number, | ||
1732 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1733 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1734 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1735 | int halted, int skipped, int actual, int non_null)) | ||
1736 | { | ||
1737 | u8 ed = ed_number - 1; | ||
1738 | wait:if (ftdi->disconnected > 0) { | ||
1739 | return -ENODEV; | ||
1740 | } else if (ftdi->initialized == 0) { | ||
1741 | return -ENODEV; | ||
1742 | } else { | ||
1743 | int command_size; | ||
1744 | down(&ftdi->u132_lock); | ||
1745 | command_size = ftdi->command_next - ftdi->command_head; | ||
1746 | if (command_size < COMMAND_SIZE) { | ||
1747 | u8 *b; | ||
1748 | u16 urb_size; | ||
1749 | int i = 0; | ||
1750 | char data[30 *3 + 4]; | ||
1751 | char *d = data; | ||
1752 | int m = (sizeof(data) - 1) / 3; | ||
1753 | int l = 0; | ||
1754 | struct u132_target *target = &ftdi->target[ed]; | ||
1755 | struct u132_command *command = &ftdi->command[ | ||
1756 | COMMAND_MASK & ftdi->command_next]; | ||
1757 | command->header = 0x81 | (ed << 5); | ||
1758 | command->address = (toggle_bits << 6) | (ep_number << 2) | ||
1759 | | (address << 0); | ||
1760 | command->width = usb_maxpacket(urb->dev, urb->pipe, | ||
1761 | usb_pipeout(urb->pipe)); | ||
1762 | command->follows = min(1024, | ||
1763 | urb->transfer_buffer_length - | ||
1764 | urb->actual_length); | ||
1765 | command->value = 0; | ||
1766 | command->buffer = urb->transfer_buffer + | ||
1767 | urb->actual_length; | ||
1768 | command->length = 0x8000 | (command->follows - 1); | ||
1769 | b = command->buffer; | ||
1770 | urb_size = command->follows; | ||
1771 | data[0] = 0; | ||
1772 | while (urb_size-- > 0) { | ||
1773 | if (i > m) { | ||
1774 | } else if (i++ < m) { | ||
1775 | int w = sprintf(d, " %02X", *b++); | ||
1776 | d += w; | ||
1777 | l += w; | ||
1778 | } else | ||
1779 | d += sprintf(d, " .."); | ||
1780 | } | ||
1781 | target->callback = callback; | ||
1782 | target->endp = endp; | ||
1783 | target->urb = urb; | ||
1784 | target->active = 1; | ||
1785 | ftdi->command_next += 1; | ||
1786 | ftdi_elan_kick_command_queue(ftdi); | ||
1787 | up(&ftdi->u132_lock); | ||
1788 | return 0; | ||
1789 | } else { | ||
1790 | up(&ftdi->u132_lock); | ||
1791 | msleep(100); | ||
1792 | goto wait; | ||
1793 | } | ||
1794 | } | ||
1795 | } | ||
1796 | |||
1797 | int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number, | ||
1798 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1799 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1800 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1801 | int halted, int skipped, int actual, int non_null)) | ||
1802 | { | ||
1803 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1804 | return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address, | ||
1805 | ep_number, toggle_bits, callback); | ||
1806 | } | ||
1807 | |||
1808 | |||
1809 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_output); | ||
1810 | static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number, | ||
1811 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1812 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1813 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1814 | int halted, int skipped, int actual, int non_null)) | ||
1815 | { | ||
1816 | u8 ed = ed_number - 1; | ||
1817 | wait:if (ftdi->disconnected > 0) { | ||
1818 | return -ENODEV; | ||
1819 | } else if (ftdi->initialized == 0) { | ||
1820 | return -ENODEV; | ||
1821 | } else { | ||
1822 | int command_size; | ||
1823 | down(&ftdi->u132_lock); | ||
1824 | command_size = ftdi->command_next - ftdi->command_head; | ||
1825 | if (command_size < COMMAND_SIZE) { | ||
1826 | int remaining_length = urb->transfer_buffer_length - | ||
1827 | urb->actual_length; | ||
1828 | struct u132_target *target = &ftdi->target[ed]; | ||
1829 | struct u132_command *command = &ftdi->command[ | ||
1830 | COMMAND_MASK & ftdi->command_next]; | ||
1831 | command->header = 0x83 | (ed << 5); | ||
1832 | if (remaining_length == 0) { | ||
1833 | command->length = 0x0000; | ||
1834 | } else if (remaining_length > 1024) { | ||
1835 | command->length = 0x8000 | 1023; | ||
1836 | } else | ||
1837 | command->length = 0x8000 | (remaining_length - | ||
1838 | 1); | ||
1839 | command->address = (toggle_bits << 6) | (ep_number << 2) | ||
1840 | | (address << 0); | ||
1841 | command->width = usb_maxpacket(urb->dev, urb->pipe, | ||
1842 | usb_pipeout(urb->pipe)); | ||
1843 | command->follows = 0; | ||
1844 | command->value = 0; | ||
1845 | command->buffer = NULL; | ||
1846 | target->callback = callback; | ||
1847 | target->endp = endp; | ||
1848 | target->urb = urb; | ||
1849 | target->active = 1; | ||
1850 | ftdi->command_next += 1; | ||
1851 | ftdi_elan_kick_command_queue(ftdi); | ||
1852 | up(&ftdi->u132_lock); | ||
1853 | return 0; | ||
1854 | } else { | ||
1855 | up(&ftdi->u132_lock); | ||
1856 | msleep(100); | ||
1857 | goto wait; | ||
1858 | } | ||
1859 | } | ||
1860 | } | ||
1861 | |||
1862 | int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number, | ||
1863 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
1864 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
1865 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
1866 | int halted, int skipped, int actual, int non_null)) | ||
1867 | { | ||
1868 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1869 | return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address, | ||
1870 | ep_number, toggle_bits, callback); | ||
1871 | } | ||
1872 | |||
1873 | |||
1874 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_single); | ||
1875 | static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number, | ||
1876 | void *endp) | ||
1877 | { | ||
1878 | u8 ed = ed_number - 1; | ||
1879 | if (ftdi->disconnected > 0) { | ||
1880 | return -ENODEV; | ||
1881 | } else if (ftdi->initialized == 0) { | ||
1882 | return -ENODEV; | ||
1883 | } else { | ||
1884 | struct u132_target *target = &ftdi->target[ed]; | ||
1885 | down(&ftdi->u132_lock); | ||
1886 | if (target->abandoning > 0) { | ||
1887 | up(&ftdi->u132_lock); | ||
1888 | return 0; | ||
1889 | } else { | ||
1890 | target->abandoning = 1; | ||
1891 | wait_1:if (target->active == 1) { | ||
1892 | int command_size = ftdi->command_next - | ||
1893 | ftdi->command_head; | ||
1894 | if (command_size < COMMAND_SIZE) { | ||
1895 | struct u132_command *command = | ||
1896 | &ftdi->command[COMMAND_MASK & | ||
1897 | ftdi->command_next]; | ||
1898 | command->header = 0x80 | (ed << 5) | | ||
1899 | 0x4; | ||
1900 | command->length = 0x00; | ||
1901 | command->address = 0x00; | ||
1902 | command->width = 0x00; | ||
1903 | command->follows = 0; | ||
1904 | command->value = 0; | ||
1905 | command->buffer = &command->value; | ||
1906 | ftdi->command_next += 1; | ||
1907 | ftdi_elan_kick_command_queue(ftdi); | ||
1908 | } else { | ||
1909 | up(&ftdi->u132_lock); | ||
1910 | msleep(100); | ||
1911 | down(&ftdi->u132_lock); | ||
1912 | goto wait_1; | ||
1913 | } | ||
1914 | } | ||
1915 | up(&ftdi->u132_lock); | ||
1916 | return 0; | ||
1917 | } | ||
1918 | } | ||
1919 | } | ||
1920 | |||
1921 | int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number, | ||
1922 | void *endp) | ||
1923 | { | ||
1924 | struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); | ||
1925 | return ftdi_elan_edset_flush(ftdi, ed_number, endp); | ||
1926 | } | ||
1927 | |||
1928 | |||
1929 | EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_flush); | ||
1930 | static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi) | ||
1931 | { | ||
1932 | int retry_on_empty = 10; | ||
1933 | int retry_on_timeout = 5; | ||
1934 | int retry_on_status = 20; | ||
1935 | more:{ | ||
1936 | int packet_bytes = 0; | ||
1937 | int retval = usb_bulk_msg(ftdi->udev, | ||
1938 | usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), | ||
1939 | ftdi->bulk_in_buffer, ftdi->bulk_in_size, | ||
1940 | &packet_bytes, msecs_to_jiffies(100)); | ||
1941 | if (packet_bytes > 2) { | ||
1942 | char diag[30 *3 + 4]; | ||
1943 | char *d = diag; | ||
1944 | int m = (sizeof(diag) - 1) / 3; | ||
1945 | char *b = ftdi->bulk_in_buffer; | ||
1946 | int bytes_read = 0; | ||
1947 | diag[0] = 0; | ||
1948 | while (packet_bytes-- > 0) { | ||
1949 | char c = *b++; | ||
1950 | if (bytes_read < m) { | ||
1951 | d += sprintf(d, " %02X", | ||
1952 | 0x000000FF & c); | ||
1953 | } else if (bytes_read > m) { | ||
1954 | } else | ||
1955 | d += sprintf(d, " .."); | ||
1956 | bytes_read += 1; | ||
1957 | continue; | ||
1958 | } | ||
1959 | goto more; | ||
1960 | } else if (packet_bytes > 1) { | ||
1961 | char s1 = ftdi->bulk_in_buffer[0]; | ||
1962 | char s2 = ftdi->bulk_in_buffer[1]; | ||
1963 | if (s1 == 0x31 && s2 == 0x60) { | ||
1964 | return 0; | ||
1965 | } else if (retry_on_status-- > 0) { | ||
1966 | goto more; | ||
1967 | } else { | ||
1968 | dev_err(&ftdi->udev->dev, "STATUS ERROR retry l" | ||
1969 | "imit reached\n"); | ||
1970 | return -EFAULT; | ||
1971 | } | ||
1972 | } else if (packet_bytes > 0) { | ||
1973 | char b1 = ftdi->bulk_in_buffer[0]; | ||
1974 | dev_err(&ftdi->udev->dev, "only one byte flushed from F" | ||
1975 | "TDI = %02X\n", b1); | ||
1976 | if (retry_on_status-- > 0) { | ||
1977 | goto more; | ||
1978 | } else { | ||
1979 | dev_err(&ftdi->udev->dev, "STATUS ERROR retry l" | ||
1980 | "imit reached\n"); | ||
1981 | return -EFAULT; | ||
1982 | } | ||
1983 | } else if (retval == -ETIMEDOUT) { | ||
1984 | if (retry_on_timeout-- > 0) { | ||
1985 | goto more; | ||
1986 | } else { | ||
1987 | dev_err(&ftdi->udev->dev, "TIMED OUT retry limi" | ||
1988 | "t reached\n"); | ||
1989 | return -ENOMEM; | ||
1990 | } | ||
1991 | } else if (retval == 0) { | ||
1992 | if (retry_on_empty-- > 0) { | ||
1993 | goto more; | ||
1994 | } else { | ||
1995 | dev_err(&ftdi->udev->dev, "empty packet retry l" | ||
1996 | "imit reached\n"); | ||
1997 | return -ENOMEM; | ||
1998 | } | ||
1999 | } else { | ||
2000 | dev_err(&ftdi->udev->dev, "error = %d\n", retval); | ||
2001 | return retval; | ||
2002 | } | ||
2003 | } | ||
2004 | return -1; | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | /* | ||
2009 | * send the long flush sequence | ||
2010 | * | ||
2011 | */ | ||
2012 | static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi) | ||
2013 | { | ||
2014 | int retval; | ||
2015 | struct urb *urb; | ||
2016 | char *buf; | ||
2017 | int I = 257; | ||
2018 | int i = 0; | ||
2019 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
2020 | if (!urb) { | ||
2021 | dev_err(&ftdi->udev->dev, "could not alloc a urb for flush sequ" | ||
2022 | "ence\n"); | ||
2023 | return -ENOMEM; | ||
2024 | } | ||
2025 | buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); | ||
2026 | if (!buf) { | ||
2027 | dev_err(&ftdi->udev->dev, "could not get a buffer for flush seq" | ||
2028 | "uence\n"); | ||
2029 | usb_free_urb(urb); | ||
2030 | return -ENOMEM; | ||
2031 | } | ||
2032 | while (I-- > 0) | ||
2033 | buf[i++] = 0x55; | ||
2034 | usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, | ||
2035 | ftdi->bulk_out_endpointAddr), buf, i, | ||
2036 | ftdi_elan_write_bulk_callback, ftdi); | ||
2037 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
2038 | retval = usb_submit_urb(urb, GFP_KERNEL); | ||
2039 | if (retval) { | ||
2040 | dev_err(&ftdi->udev->dev, "failed to submit urb containing the " | ||
2041 | "flush sequence\n"); | ||
2042 | usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma); | ||
2043 | usb_free_urb(urb); | ||
2044 | return -ENOMEM; | ||
2045 | } | ||
2046 | usb_free_urb(urb); | ||
2047 | return 0; | ||
2048 | } | ||
2049 | |||
2050 | |||
2051 | /* | ||
2052 | * send the reset sequence | ||
2053 | * | ||
2054 | */ | ||
2055 | static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi) | ||
2056 | { | ||
2057 | int retval; | ||
2058 | struct urb *urb; | ||
2059 | char *buf; | ||
2060 | int I = 4; | ||
2061 | int i = 0; | ||
2062 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
2063 | if (!urb) { | ||
2064 | dev_err(&ftdi->udev->dev, "could not get a urb for the reset se" | ||
2065 | "quence\n"); | ||
2066 | return -ENOMEM; | ||
2067 | } | ||
2068 | buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma); | ||
2069 | if (!buf) { | ||
2070 | dev_err(&ftdi->udev->dev, "could not get a buffer for the reset" | ||
2071 | " sequence\n"); | ||
2072 | usb_free_urb(urb); | ||
2073 | return -ENOMEM; | ||
2074 | } | ||
2075 | buf[i++] = 0x55; | ||
2076 | buf[i++] = 0xAA; | ||
2077 | buf[i++] = 0x5A; | ||
2078 | buf[i++] = 0xA5; | ||
2079 | usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, | ||
2080 | ftdi->bulk_out_endpointAddr), buf, i, | ||
2081 | ftdi_elan_write_bulk_callback, ftdi); | ||
2082 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
2083 | retval = usb_submit_urb(urb, GFP_KERNEL); | ||
2084 | if (retval) { | ||
2085 | dev_err(&ftdi->udev->dev, "failed to submit urb containing the " | ||
2086 | "reset sequence\n"); | ||
2087 | usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma); | ||
2088 | usb_free_urb(urb); | ||
2089 | return -ENOMEM; | ||
2090 | } | ||
2091 | usb_free_urb(urb); | ||
2092 | return 0; | ||
2093 | } | ||
2094 | |||
2095 | static int ftdi_elan_synchronize(struct usb_ftdi *ftdi) | ||
2096 | { | ||
2097 | int retval; | ||
2098 | int long_stop = 10; | ||
2099 | int retry_on_timeout = 5; | ||
2100 | int retry_on_empty = 10; | ||
2101 | int err_count = 0; | ||
2102 | retval = ftdi_elan_flush_input_fifo(ftdi); | ||
2103 | if (retval) | ||
2104 | return retval; | ||
2105 | ftdi->bulk_in_left = 0; | ||
2106 | ftdi->bulk_in_last = -1; | ||
2107 | while (long_stop-- > 0) { | ||
2108 | int read_stop; | ||
2109 | int read_stuck; | ||
2110 | retval = ftdi_elan_synchronize_flush(ftdi); | ||
2111 | if (retval) | ||
2112 | return retval; | ||
2113 | retval = ftdi_elan_flush_input_fifo(ftdi); | ||
2114 | if (retval) | ||
2115 | return retval; | ||
2116 | reset:retval = ftdi_elan_synchronize_reset(ftdi); | ||
2117 | if (retval) | ||
2118 | return retval; | ||
2119 | read_stop = 100; | ||
2120 | read_stuck = 10; | ||
2121 | read:{ | ||
2122 | int packet_bytes = 0; | ||
2123 | retval = usb_bulk_msg(ftdi->udev, | ||
2124 | usb_rcvbulkpipe(ftdi->udev, | ||
2125 | ftdi->bulk_in_endpointAddr), | ||
2126 | ftdi->bulk_in_buffer, ftdi->bulk_in_size, | ||
2127 | &packet_bytes, msecs_to_jiffies(500)); | ||
2128 | if (packet_bytes > 2) { | ||
2129 | char diag[30 *3 + 4]; | ||
2130 | char *d = diag; | ||
2131 | int m = (sizeof(diag) - 1) / 3; | ||
2132 | char *b = ftdi->bulk_in_buffer; | ||
2133 | int bytes_read = 0; | ||
2134 | unsigned char c = 0; | ||
2135 | diag[0] = 0; | ||
2136 | while (packet_bytes-- > 0) { | ||
2137 | c = *b++; | ||
2138 | if (bytes_read < m) { | ||
2139 | d += sprintf(d, " %02X", c); | ||
2140 | } else if (bytes_read > m) { | ||
2141 | } else | ||
2142 | d += sprintf(d, " .."); | ||
2143 | bytes_read += 1; | ||
2144 | continue; | ||
2145 | } | ||
2146 | if (c == 0x7E) { | ||
2147 | return 0; | ||
2148 | } else { | ||
2149 | if (c == 0x55) { | ||
2150 | goto read; | ||
2151 | } else if (read_stop-- > 0) { | ||
2152 | goto read; | ||
2153 | } else { | ||
2154 | dev_err(&ftdi->udev->dev, "retr" | ||
2155 | "y limit reached\n"); | ||
2156 | continue; | ||
2157 | } | ||
2158 | } | ||
2159 | } else if (packet_bytes > 1) { | ||
2160 | unsigned char s1 = ftdi->bulk_in_buffer[0]; | ||
2161 | unsigned char s2 = ftdi->bulk_in_buffer[1]; | ||
2162 | if (s1 == 0x31 && s2 == 0x00) { | ||
2163 | if (read_stuck-- > 0) { | ||
2164 | goto read; | ||
2165 | } else | ||
2166 | goto reset; | ||
2167 | } else if (s1 == 0x31 && s2 == 0x60) { | ||
2168 | if (read_stop-- > 0) { | ||
2169 | goto read; | ||
2170 | } else { | ||
2171 | dev_err(&ftdi->udev->dev, "retr" | ||
2172 | "y limit reached\n"); | ||
2173 | continue; | ||
2174 | } | ||
2175 | } else { | ||
2176 | if (read_stop-- > 0) { | ||
2177 | goto read; | ||
2178 | } else { | ||
2179 | dev_err(&ftdi->udev->dev, "retr" | ||
2180 | "y limit reached\n"); | ||
2181 | continue; | ||
2182 | } | ||
2183 | } | ||
2184 | } else if (packet_bytes > 0) { | ||
2185 | if (read_stop-- > 0) { | ||
2186 | goto read; | ||
2187 | } else { | ||
2188 | dev_err(&ftdi->udev->dev, "retry limit " | ||
2189 | "reached\n"); | ||
2190 | continue; | ||
2191 | } | ||
2192 | } else if (retval == -ETIMEDOUT) { | ||
2193 | if (retry_on_timeout-- > 0) { | ||
2194 | goto read; | ||
2195 | } else { | ||
2196 | dev_err(&ftdi->udev->dev, "TIMED OUT re" | ||
2197 | "try limit reached\n"); | ||
2198 | continue; | ||
2199 | } | ||
2200 | } else if (retval == 0) { | ||
2201 | if (retry_on_empty-- > 0) { | ||
2202 | goto read; | ||
2203 | } else { | ||
2204 | dev_err(&ftdi->udev->dev, "empty packet" | ||
2205 | " retry limit reached\n"); | ||
2206 | continue; | ||
2207 | } | ||
2208 | } else { | ||
2209 | err_count += 1; | ||
2210 | dev_err(&ftdi->udev->dev, "error = %d\n", | ||
2211 | retval); | ||
2212 | if (read_stop-- > 0) { | ||
2213 | goto read; | ||
2214 | } else { | ||
2215 | dev_err(&ftdi->udev->dev, "retry limit " | ||
2216 | "reached\n"); | ||
2217 | continue; | ||
2218 | } | ||
2219 | } | ||
2220 | } | ||
2221 | } | ||
2222 | dev_err(&ftdi->udev->dev, "failed to synchronize\n"); | ||
2223 | return -EFAULT; | ||
2224 | } | ||
2225 | |||
2226 | static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi) | ||
2227 | { | ||
2228 | int retry_on_empty = 10; | ||
2229 | int retry_on_timeout = 5; | ||
2230 | int retry_on_status = 50; | ||
2231 | more:{ | ||
2232 | int packet_bytes = 0; | ||
2233 | int retval = usb_bulk_msg(ftdi->udev, | ||
2234 | usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), | ||
2235 | ftdi->bulk_in_buffer, ftdi->bulk_in_size, | ||
2236 | &packet_bytes, msecs_to_jiffies(1000)); | ||
2237 | if (packet_bytes > 2) { | ||
2238 | char diag[30 *3 + 4]; | ||
2239 | char *d = diag; | ||
2240 | int m = (sizeof(diag) - 1) / 3; | ||
2241 | char *b = ftdi->bulk_in_buffer; | ||
2242 | int bytes_read = 0; | ||
2243 | diag[0] = 0; | ||
2244 | while (packet_bytes-- > 0) { | ||
2245 | char c = *b++; | ||
2246 | if (bytes_read < m) { | ||
2247 | d += sprintf(d, " %02X", | ||
2248 | 0x000000FF & c); | ||
2249 | } else if (bytes_read > m) { | ||
2250 | } else | ||
2251 | d += sprintf(d, " .."); | ||
2252 | bytes_read += 1; | ||
2253 | continue; | ||
2254 | } | ||
2255 | goto more; | ||
2256 | } else if (packet_bytes > 1) { | ||
2257 | char s1 = ftdi->bulk_in_buffer[0]; | ||
2258 | char s2 = ftdi->bulk_in_buffer[1]; | ||
2259 | if (s1 == 0x31 && s2 == 0x60) { | ||
2260 | return 0; | ||
2261 | } else if (retry_on_status-- > 0) { | ||
2262 | msleep(5); | ||
2263 | goto more; | ||
2264 | } else | ||
2265 | return -EFAULT; | ||
2266 | } else if (packet_bytes > 0) { | ||
2267 | char b1 = ftdi->bulk_in_buffer[0]; | ||
2268 | dev_err(&ftdi->udev->dev, "only one byte flushed from F" | ||
2269 | "TDI = %02X\n", b1); | ||
2270 | if (retry_on_status-- > 0) { | ||
2271 | msleep(5); | ||
2272 | goto more; | ||
2273 | } else { | ||
2274 | dev_err(&ftdi->udev->dev, "STATUS ERROR retry l" | ||
2275 | "imit reached\n"); | ||
2276 | return -EFAULT; | ||
2277 | } | ||
2278 | } else if (retval == -ETIMEDOUT) { | ||
2279 | if (retry_on_timeout-- > 0) { | ||
2280 | goto more; | ||
2281 | } else { | ||
2282 | dev_err(&ftdi->udev->dev, "TIMED OUT retry limi" | ||
2283 | "t reached\n"); | ||
2284 | return -ENOMEM; | ||
2285 | } | ||
2286 | } else if (retval == 0) { | ||
2287 | if (retry_on_empty-- > 0) { | ||
2288 | goto more; | ||
2289 | } else { | ||
2290 | dev_err(&ftdi->udev->dev, "empty packet retry l" | ||
2291 | "imit reached\n"); | ||
2292 | return -ENOMEM; | ||
2293 | } | ||
2294 | } else { | ||
2295 | dev_err(&ftdi->udev->dev, "error = %d\n", retval); | ||
2296 | return -ENOMEM; | ||
2297 | } | ||
2298 | } | ||
2299 | return -1; | ||
2300 | } | ||
2301 | |||
2302 | static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi) | ||
2303 | { | ||
2304 | int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg); | ||
2305 | if (UxxxStatus) | ||
2306 | return UxxxStatus; | ||
2307 | if (ftdi->controlreg & 0x00400000) { | ||
2308 | if (ftdi->card_ejected) { | ||
2309 | } else { | ||
2310 | ftdi->card_ejected = 1; | ||
2311 | dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = " | ||
2312 | "%08X\n", ftdi->controlreg); | ||
2313 | } | ||
2314 | return -ENODEV; | ||
2315 | } else { | ||
2316 | u8 fn = ftdi->function - 1; | ||
2317 | int activePCIfn = fn << 8; | ||
2318 | u32 pcidata; | ||
2319 | u32 pciVID; | ||
2320 | u32 pciPID; | ||
2321 | int reg = 0; | ||
2322 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2323 | &pcidata); | ||
2324 | if (UxxxStatus) | ||
2325 | return UxxxStatus; | ||
2326 | pciVID = pcidata & 0xFFFF; | ||
2327 | pciPID = (pcidata >> 16) & 0xFFFF; | ||
2328 | if (pciVID == ftdi->platform_data.vendor && pciPID == | ||
2329 | ftdi->platform_data.device) { | ||
2330 | return 0; | ||
2331 | } else { | ||
2332 | dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X devi" | ||
2333 | "ce=%04X pciPID=%04X\n", | ||
2334 | ftdi->platform_data.vendor, pciVID, | ||
2335 | ftdi->platform_data.device, pciPID); | ||
2336 | return -ENODEV; | ||
2337 | } | ||
2338 | } | ||
2339 | } | ||
2340 | |||
2341 | static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi) | ||
2342 | { | ||
2343 | u32 latence_timer; | ||
2344 | u32 controlreg; | ||
2345 | int UxxxStatus; | ||
2346 | u32 pcidata; | ||
2347 | int reg = 0; | ||
2348 | int foundOHCI = 0; | ||
2349 | u8 fn; | ||
2350 | int activePCIfn = 0; | ||
2351 | u32 pciVID = 0; | ||
2352 | u32 pciPID = 0; | ||
2353 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2354 | if (UxxxStatus) | ||
2355 | return UxxxStatus; | ||
2356 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L); | ||
2357 | if (UxxxStatus) | ||
2358 | return UxxxStatus; | ||
2359 | msleep(750); | ||
2360 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100); | ||
2361 | if (UxxxStatus) | ||
2362 | return UxxxStatus; | ||
2363 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500); | ||
2364 | if (UxxxStatus) | ||
2365 | return UxxxStatus; | ||
2366 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2367 | if (UxxxStatus) | ||
2368 | return UxxxStatus; | ||
2369 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000); | ||
2370 | if (UxxxStatus) | ||
2371 | return UxxxStatus; | ||
2372 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000); | ||
2373 | if (UxxxStatus) | ||
2374 | return UxxxStatus; | ||
2375 | msleep(250); | ||
2376 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000); | ||
2377 | if (UxxxStatus) | ||
2378 | return UxxxStatus; | ||
2379 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2380 | if (UxxxStatus) | ||
2381 | return UxxxStatus; | ||
2382 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800); | ||
2383 | if (UxxxStatus) | ||
2384 | return UxxxStatus; | ||
2385 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2386 | if (UxxxStatus) | ||
2387 | return UxxxStatus; | ||
2388 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2389 | if (UxxxStatus) | ||
2390 | return UxxxStatus; | ||
2391 | msleep(1000); | ||
2392 | for (fn = 0; (fn < 4) && (!foundOHCI); fn++) { | ||
2393 | activePCIfn = fn << 8; | ||
2394 | ftdi->function = fn + 1; | ||
2395 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2396 | &pcidata); | ||
2397 | if (UxxxStatus) | ||
2398 | return UxxxStatus; | ||
2399 | pciVID = pcidata & 0xFFFF; | ||
2400 | pciPID = (pcidata >> 16) & 0xFFFF; | ||
2401 | if ((pciVID == 0x1045) && (pciPID == 0xc861)) { | ||
2402 | foundOHCI = 1; | ||
2403 | } else if ((pciVID == 0x1033) && (pciPID == 0x0035)) { | ||
2404 | foundOHCI = 1; | ||
2405 | } else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) { | ||
2406 | foundOHCI = 1; | ||
2407 | } else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) { | ||
2408 | foundOHCI = 1; | ||
2409 | } else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) { | ||
2410 | } | ||
2411 | } | ||
2412 | if (foundOHCI == 0) { | ||
2413 | return -ENXIO; | ||
2414 | } | ||
2415 | ftdi->platform_data.vendor = pciVID; | ||
2416 | ftdi->platform_data.device = pciPID; | ||
2417 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); | ||
2418 | if (UxxxStatus) | ||
2419 | return UxxxStatus; | ||
2420 | reg = 16; | ||
2421 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, | ||
2422 | 0xFFFFFFFF); | ||
2423 | if (UxxxStatus) | ||
2424 | return UxxxStatus; | ||
2425 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2426 | &pcidata); | ||
2427 | if (UxxxStatus) | ||
2428 | return UxxxStatus; | ||
2429 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, | ||
2430 | 0xF0000000); | ||
2431 | if (UxxxStatus) | ||
2432 | return UxxxStatus; | ||
2433 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2434 | &pcidata); | ||
2435 | if (UxxxStatus) | ||
2436 | return UxxxStatus; | ||
2437 | reg = 12; | ||
2438 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2439 | &latence_timer); | ||
2440 | if (UxxxStatus) | ||
2441 | return UxxxStatus; | ||
2442 | latence_timer &= 0xFFFF00FF; | ||
2443 | latence_timer |= 0x00001600; | ||
2444 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, | ||
2445 | latence_timer); | ||
2446 | if (UxxxStatus) | ||
2447 | return UxxxStatus; | ||
2448 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2449 | &pcidata); | ||
2450 | if (UxxxStatus) | ||
2451 | return UxxxStatus; | ||
2452 | reg = 4; | ||
2453 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, | ||
2454 | 0x06); | ||
2455 | if (UxxxStatus) | ||
2456 | return UxxxStatus; | ||
2457 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2458 | &pcidata); | ||
2459 | if (UxxxStatus) | ||
2460 | return UxxxStatus; | ||
2461 | return 0; | ||
2462 | } | ||
2463 | |||
2464 | static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi) | ||
2465 | { | ||
2466 | u32 pcidata; | ||
2467 | int U132Status; | ||
2468 | int reg; | ||
2469 | int reset_repeat = 0; | ||
2470 | do_reset:reg = 8; | ||
2471 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01); | ||
2472 | if (U132Status) | ||
2473 | return U132Status; | ||
2474 | reset_check:{ | ||
2475 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2476 | if (U132Status) | ||
2477 | return U132Status; | ||
2478 | if (pcidata & 1) { | ||
2479 | msleep(500); | ||
2480 | if (reset_repeat++ > 100) { | ||
2481 | reset_repeat = 0; | ||
2482 | goto do_reset; | ||
2483 | } else | ||
2484 | goto reset_check; | ||
2485 | } | ||
2486 | } | ||
2487 | goto dump_regs; | ||
2488 | msleep(500); | ||
2489 | reg = 0x28; | ||
2490 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000); | ||
2491 | if (U132Status) | ||
2492 | return U132Status; | ||
2493 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2494 | if (U132Status) | ||
2495 | return U132Status; | ||
2496 | reg = 0x40; | ||
2497 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf); | ||
2498 | if (U132Status) | ||
2499 | return U132Status; | ||
2500 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2501 | if (U132Status) | ||
2502 | return U132Status; | ||
2503 | reg = 0x34; | ||
2504 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf); | ||
2505 | if (U132Status) | ||
2506 | return U132Status; | ||
2507 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2508 | if (U132Status) | ||
2509 | return U132Status; | ||
2510 | reg = 4; | ||
2511 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0); | ||
2512 | if (U132Status) | ||
2513 | return U132Status; | ||
2514 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2515 | if (U132Status) | ||
2516 | return U132Status; | ||
2517 | msleep(250); | ||
2518 | reg = 8; | ||
2519 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04); | ||
2520 | if (U132Status) | ||
2521 | return U132Status; | ||
2522 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2523 | if (U132Status) | ||
2524 | return U132Status; | ||
2525 | reg = 0x28; | ||
2526 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2527 | if (U132Status) | ||
2528 | return U132Status; | ||
2529 | reg = 8; | ||
2530 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2531 | if (U132Status) | ||
2532 | return U132Status; | ||
2533 | reg = 0x48; | ||
2534 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200); | ||
2535 | if (U132Status) | ||
2536 | return U132Status; | ||
2537 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2538 | if (U132Status) | ||
2539 | return U132Status; | ||
2540 | reg = 0x54; | ||
2541 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2542 | if (U132Status) | ||
2543 | return U132Status; | ||
2544 | reg = 0x58; | ||
2545 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2546 | if (U132Status) | ||
2547 | return U132Status; | ||
2548 | reg = 0x34; | ||
2549 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf); | ||
2550 | if (U132Status) | ||
2551 | return U132Status; | ||
2552 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2553 | if (U132Status) | ||
2554 | return U132Status; | ||
2555 | msleep(100); | ||
2556 | reg = 0x50; | ||
2557 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000); | ||
2558 | if (U132Status) | ||
2559 | return U132Status; | ||
2560 | reg = 0x54; | ||
2561 | power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2562 | if (U132Status) | ||
2563 | return U132Status; | ||
2564 | if (!(pcidata & 1)) { | ||
2565 | msleep(500); | ||
2566 | goto power_check; | ||
2567 | } | ||
2568 | msleep(3000); | ||
2569 | reg = 0x54; | ||
2570 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2571 | if (U132Status) | ||
2572 | return U132Status; | ||
2573 | reg = 0x58; | ||
2574 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2575 | if (U132Status) | ||
2576 | return U132Status; | ||
2577 | reg = 0x54; | ||
2578 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02); | ||
2579 | if (U132Status) | ||
2580 | return U132Status; | ||
2581 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2582 | if (U132Status) | ||
2583 | return U132Status; | ||
2584 | reg = 0x54; | ||
2585 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10); | ||
2586 | if (U132Status) | ||
2587 | return U132Status; | ||
2588 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2589 | if (U132Status) | ||
2590 | return U132Status; | ||
2591 | msleep(750); | ||
2592 | reg = 0x54; | ||
2593 | if (0) { | ||
2594 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02); | ||
2595 | if (U132Status) | ||
2596 | return U132Status; | ||
2597 | } | ||
2598 | if (0) { | ||
2599 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2600 | if (U132Status) | ||
2601 | return U132Status; | ||
2602 | } | ||
2603 | reg = 0x54; | ||
2604 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2605 | if (U132Status) | ||
2606 | return U132Status; | ||
2607 | reg = 0x58; | ||
2608 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2609 | if (U132Status) | ||
2610 | return U132Status; | ||
2611 | dump_regs:for (reg = 0; reg <= 0x54; reg += 4) { | ||
2612 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2613 | if (U132Status) | ||
2614 | return U132Status; | ||
2615 | } | ||
2616 | return 0; | ||
2617 | } | ||
2618 | |||
2619 | |||
2620 | /* | ||
2621 | * we use only the first bulk-in and bulk-out endpoints | ||
2622 | */ | ||
2623 | static int ftdi_elan_probe(struct usb_interface *interface, | ||
2624 | const struct usb_device_id *id) | ||
2625 | { | ||
2626 | struct usb_host_interface *iface_desc; | ||
2627 | struct usb_endpoint_descriptor *endpoint; | ||
2628 | size_t buffer_size; | ||
2629 | int i; | ||
2630 | int retval = -ENOMEM; | ||
2631 | struct usb_ftdi *ftdi = kmalloc(sizeof(struct usb_ftdi), GFP_KERNEL); | ||
2632 | if (ftdi == NULL) { | ||
2633 | printk(KERN_ERR "Out of memory\n"); | ||
2634 | return -ENOMEM; | ||
2635 | } | ||
2636 | memset(ftdi, 0x00, sizeof(struct usb_ftdi)); | ||
2637 | down(&ftdi_module_lock); | ||
2638 | list_add_tail(&ftdi->ftdi_list, &ftdi_static_list); | ||
2639 | ftdi->sequence_num = ++ftdi_instances; | ||
2640 | up(&ftdi_module_lock); | ||
2641 | ftdi_elan_init_kref(ftdi); | ||
2642 | init_MUTEX(&ftdi->sw_lock); | ||
2643 | ftdi->udev = usb_get_dev(interface_to_usbdev(interface)); | ||
2644 | ftdi->interface = interface; | ||
2645 | init_MUTEX(&ftdi->u132_lock); | ||
2646 | ftdi->expected = 4; | ||
2647 | iface_desc = interface->cur_altsetting; | ||
2648 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
2649 | endpoint = &iface_desc->endpoint[i].desc; | ||
2650 | if (!ftdi->bulk_in_endpointAddr && | ||
2651 | ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
2652 | == USB_DIR_IN) && ((endpoint->bmAttributes & | ||
2653 | USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) | ||
2654 | { | ||
2655 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
2656 | ftdi->bulk_in_size = buffer_size; | ||
2657 | ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
2658 | ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
2659 | if (!ftdi->bulk_in_buffer) { | ||
2660 | dev_err(&ftdi->udev->dev, "Could not allocate b" | ||
2661 | "ulk_in_buffer\n"); | ||
2662 | retval = -ENOMEM; | ||
2663 | goto error; | ||
2664 | } | ||
2665 | } | ||
2666 | if (!ftdi->bulk_out_endpointAddr && | ||
2667 | ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
2668 | == USB_DIR_OUT) && ((endpoint->bmAttributes & | ||
2669 | USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) | ||
2670 | { | ||
2671 | ftdi->bulk_out_endpointAddr = | ||
2672 | endpoint->bEndpointAddress; | ||
2673 | } | ||
2674 | } | ||
2675 | if (!(ftdi->bulk_in_endpointAddr && ftdi->bulk_out_endpointAddr)) { | ||
2676 | dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk" | ||
2677 | "-out endpoints\n"); | ||
2678 | retval = -ENODEV; | ||
2679 | goto error; | ||
2680 | } | ||
2681 | dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n", | ||
2682 | iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr, | ||
2683 | ftdi->bulk_out_endpointAddr); | ||
2684 | usb_set_intfdata(interface, ftdi); | ||
2685 | if (iface_desc->desc.bInterfaceNumber == 0 && | ||
2686 | ftdi->bulk_in_endpointAddr == 0x81 && | ||
2687 | ftdi->bulk_out_endpointAddr == 0x02) { | ||
2688 | retval = usb_register_dev(interface, &ftdi_elan_jtag_class); | ||
2689 | if (retval) { | ||
2690 | dev_err(&ftdi->udev->dev, "Not able to get a minor for " | ||
2691 | "this device.\n"); | ||
2692 | usb_set_intfdata(interface, NULL); | ||
2693 | retval = -ENOMEM; | ||
2694 | goto error; | ||
2695 | } else { | ||
2696 | ftdi->class = &ftdi_elan_jtag_class; | ||
2697 | dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface " | ||
2698 | "%d now attached to ftdi%d\n", ftdi, | ||
2699 | iface_desc->desc.bInterfaceNumber, | ||
2700 | interface->minor); | ||
2701 | return 0; | ||
2702 | } | ||
2703 | } else if (iface_desc->desc.bInterfaceNumber == 1 && | ||
2704 | ftdi->bulk_in_endpointAddr == 0x83 && | ||
2705 | ftdi->bulk_out_endpointAddr == 0x04) { | ||
2706 | ftdi->class = NULL; | ||
2707 | dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a" | ||
2708 | "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber); | ||
2709 | INIT_WORK(&ftdi->status_work, ftdi_elan_status_work, | ||
2710 | (void *)ftdi); | ||
2711 | INIT_WORK(&ftdi->command_work, ftdi_elan_command_work, | ||
2712 | (void *)ftdi); | ||
2713 | INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work, | ||
2714 | (void *)ftdi); | ||
2715 | ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000)); | ||
2716 | return 0; | ||
2717 | } else { | ||
2718 | dev_err(&ftdi->udev->dev, | ||
2719 | "Could not find ELAN's U132 device\n"); | ||
2720 | retval = -ENODEV; | ||
2721 | goto error; | ||
2722 | } | ||
2723 | error:if (ftdi) { | ||
2724 | ftdi_elan_put_kref(ftdi); | ||
2725 | } | ||
2726 | return retval; | ||
2727 | } | ||
2728 | |||
2729 | static void ftdi_elan_disconnect(struct usb_interface *interface) | ||
2730 | { | ||
2731 | struct usb_ftdi *ftdi = usb_get_intfdata(interface); | ||
2732 | ftdi->disconnected += 1; | ||
2733 | if (ftdi->class) { | ||
2734 | int minor = interface->minor; | ||
2735 | struct usb_class_driver *class = ftdi->class; | ||
2736 | usb_set_intfdata(interface, NULL); | ||
2737 | usb_deregister_dev(interface, class); | ||
2738 | dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on min" | ||
2739 | "or %d now disconnected\n", minor); | ||
2740 | } else { | ||
2741 | ftdi_status_cancel_work(ftdi); | ||
2742 | ftdi_command_cancel_work(ftdi); | ||
2743 | ftdi_response_cancel_work(ftdi); | ||
2744 | ftdi_elan_abandon_completions(ftdi); | ||
2745 | ftdi_elan_abandon_targets(ftdi); | ||
2746 | if (ftdi->registered) { | ||
2747 | platform_device_unregister(&ftdi->platform_dev); | ||
2748 | ftdi->synchronized = 0; | ||
2749 | ftdi->enumerated = 0; | ||
2750 | ftdi->registered = 0; | ||
2751 | } | ||
2752 | flush_workqueue(status_queue); | ||
2753 | flush_workqueue(command_queue); | ||
2754 | flush_workqueue(respond_queue); | ||
2755 | ftdi->disconnected += 1; | ||
2756 | usb_set_intfdata(interface, NULL); | ||
2757 | dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller inter" | ||
2758 | "face now disconnected\n"); | ||
2759 | } | ||
2760 | ftdi_elan_put_kref(ftdi); | ||
2761 | } | ||
2762 | |||
2763 | static struct usb_driver ftdi_elan_driver = { | ||
2764 | .name = "ftdi-elan", | ||
2765 | .probe = ftdi_elan_probe, | ||
2766 | .disconnect = ftdi_elan_disconnect, | ||
2767 | .id_table = ftdi_elan_table, | ||
2768 | }; | ||
2769 | static int __init ftdi_elan_init(void) | ||
2770 | { | ||
2771 | int result; | ||
2772 | printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, | ||
2773 | __TIME__, __DATE__); | ||
2774 | init_MUTEX(&ftdi_module_lock); | ||
2775 | INIT_LIST_HEAD(&ftdi_static_list); | ||
2776 | status_queue = create_singlethread_workqueue("ftdi-status-control"); | ||
2777 | command_queue = create_singlethread_workqueue("ftdi-command-engine"); | ||
2778 | respond_queue = create_singlethread_workqueue("ftdi-respond-engine"); | ||
2779 | result = usb_register(&ftdi_elan_driver); | ||
2780 | if (result) | ||
2781 | printk(KERN_ERR "usb_register failed. Error number %d\n", | ||
2782 | result); | ||
2783 | return result; | ||
2784 | } | ||
2785 | |||
2786 | static void __exit ftdi_elan_exit(void) | ||
2787 | { | ||
2788 | struct usb_ftdi *ftdi; | ||
2789 | struct usb_ftdi *temp; | ||
2790 | usb_deregister(&ftdi_elan_driver); | ||
2791 | printk(KERN_INFO "ftdi_u132 driver deregistered\n"); | ||
2792 | list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) { | ||
2793 | ftdi_status_cancel_work(ftdi); | ||
2794 | ftdi_command_cancel_work(ftdi); | ||
2795 | ftdi_response_cancel_work(ftdi); | ||
2796 | } flush_workqueue(status_queue); | ||
2797 | destroy_workqueue(status_queue); | ||
2798 | status_queue = NULL; | ||
2799 | flush_workqueue(command_queue); | ||
2800 | destroy_workqueue(command_queue); | ||
2801 | command_queue = NULL; | ||
2802 | flush_workqueue(respond_queue); | ||
2803 | destroy_workqueue(respond_queue); | ||
2804 | respond_queue = NULL; | ||
2805 | } | ||
2806 | |||
2807 | |||
2808 | module_init(ftdi_elan_init); | ||
2809 | module_exit(ftdi_elan_exit); | ||
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index fcd69c52aea9..8e6e195a22ba 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c | |||
@@ -98,7 +98,7 @@ static int idmouse_probe(struct usb_interface *interface, | |||
98 | static void idmouse_disconnect(struct usb_interface *interface); | 98 | static void idmouse_disconnect(struct usb_interface *interface); |
99 | 99 | ||
100 | /* file operation pointers */ | 100 | /* file operation pointers */ |
101 | static struct file_operations idmouse_fops = { | 101 | static const struct file_operations idmouse_fops = { |
102 | .owner = THIS_MODULE, | 102 | .owner = THIS_MODULE, |
103 | .read = idmouse_read, | 103 | .read = idmouse_read, |
104 | .open = idmouse_open, | 104 | .open = idmouse_open, |
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index f30ab1fbb3c8..10b640339d8d 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c | |||
@@ -589,7 +589,7 @@ exit: | |||
589 | } | 589 | } |
590 | 590 | ||
591 | /* file operations needed when we register this driver */ | 591 | /* file operations needed when we register this driver */ |
592 | static struct file_operations ld_usb_fops = { | 592 | static const struct file_operations ld_usb_fops = { |
593 | .owner = THIS_MODULE, | 593 | .owner = THIS_MODULE, |
594 | .read = ld_usb_read, | 594 | .read = ld_usb_read, |
595 | .write = ld_usb_write, | 595 | .write = ld_usb_write, |
@@ -657,15 +657,11 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * | |||
657 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 657 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
658 | endpoint = &iface_desc->endpoint[i].desc; | 658 | endpoint = &iface_desc->endpoint[i].desc; |
659 | 659 | ||
660 | if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && | 660 | if (usb_endpoint_is_int_in(endpoint)) |
661 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { | ||
662 | dev->interrupt_in_endpoint = endpoint; | 661 | dev->interrupt_in_endpoint = endpoint; |
663 | } | ||
664 | 662 | ||
665 | if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && | 663 | if (usb_endpoint_is_int_out(endpoint)) |
666 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { | ||
667 | dev->interrupt_out_endpoint = endpoint; | 664 | dev->interrupt_out_endpoint = endpoint; |
668 | } | ||
669 | } | 665 | } |
670 | if (dev->interrupt_in_endpoint == NULL) { | 666 | if (dev->interrupt_in_endpoint == NULL) { |
671 | dev_err(&intf->dev, "Interrupt in endpoint not found\n"); | 667 | dev_err(&intf->dev, "Interrupt in endpoint not found\n"); |
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 7699d970e680..77c36e63c7bf 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c | |||
@@ -259,7 +259,7 @@ static void tower_disconnect (struct usb_interface *interface); | |||
259 | static DEFINE_MUTEX (disconnect_mutex); | 259 | static DEFINE_MUTEX (disconnect_mutex); |
260 | 260 | ||
261 | /* file operations needed when we register this driver */ | 261 | /* file operations needed when we register this driver */ |
262 | static struct file_operations tower_fops = { | 262 | static const struct file_operations tower_fops = { |
263 | .owner = THIS_MODULE, | 263 | .owner = THIS_MODULE, |
264 | .read = tower_read, | 264 | .read = tower_read, |
265 | .write = tower_write, | 265 | .write = tower_write, |
diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c new file mode 100644 index 000000000000..735ed33f4f7f --- /dev/null +++ b/drivers/usb/misc/phidget.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * USB Phidgets class | ||
3 | * | ||
4 | * Copyright (C) 2006 Sean Young <sean@mess.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/device.h> | ||
17 | |||
18 | struct class *phidget_class; | ||
19 | |||
20 | static int __init init_phidget(void) | ||
21 | { | ||
22 | phidget_class = class_create(THIS_MODULE, "phidget"); | ||
23 | |||
24 | if (IS_ERR(phidget_class)) | ||
25 | return PTR_ERR(phidget_class); | ||
26 | |||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | static void __exit cleanup_phidget(void) | ||
31 | { | ||
32 | class_destroy(phidget_class); | ||
33 | } | ||
34 | |||
35 | EXPORT_SYMBOL_GPL(phidget_class); | ||
36 | |||
37 | module_init(init_phidget); | ||
38 | module_exit(cleanup_phidget); | ||
39 | |||
40 | MODULE_LICENSE("GPL"); | ||
41 | MODULE_AUTHOR("Sean Young <sean@mess.org>"); | ||
42 | MODULE_DESCRIPTION("Container module for phidget class"); | ||
43 | |||
diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h new file mode 100644 index 000000000000..c4011907d431 --- /dev/null +++ b/drivers/usb/misc/phidget.h | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * USB Phidgets class | ||
3 | * | ||
4 | * Copyright (C) 2006 Sean Young <sean@mess.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | extern struct class *phidget_class; | ||
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index bfbbbfbb92bc..9a8d137d39f9 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
22 | 22 | ||
23 | #include "phidget.h" | ||
24 | |||
23 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | 25 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
24 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" | 26 | #define DRIVER_DESC "USB PhidgetInterfaceKit Driver" |
25 | 27 | ||
@@ -57,11 +59,15 @@ ifkit(8, 8, 4, 0); | |||
57 | ifkit(0, 8, 8, 1); | 59 | ifkit(0, 8, 8, 1); |
58 | ifkit(0, 16, 16, 0); | 60 | ifkit(0, 16, 16, 0); |
59 | 61 | ||
62 | static unsigned long device_no; | ||
63 | |||
60 | struct interfacekit { | 64 | struct interfacekit { |
61 | struct usb_device *udev; | 65 | struct usb_device *udev; |
62 | struct usb_interface *intf; | 66 | struct usb_interface *intf; |
63 | struct driver_interfacekit *ifkit; | 67 | struct driver_interfacekit *ifkit; |
68 | struct device *dev; | ||
64 | unsigned long outputs; | 69 | unsigned long outputs; |
70 | int dev_no; | ||
65 | u8 inputs[MAX_INTERFACES]; | 71 | u8 inputs[MAX_INTERFACES]; |
66 | u16 sensors[MAX_INTERFACES]; | 72 | u16 sensors[MAX_INTERFACES]; |
67 | u8 lcd_files_on; | 73 | u8 lcd_files_on; |
@@ -180,21 +186,24 @@ exit: | |||
180 | } | 186 | } |
181 | 187 | ||
182 | #define set_lcd_line(number) \ | 188 | #define set_lcd_line(number) \ |
183 | static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ | 189 | static ssize_t lcd_line_##number(struct device *dev, \ |
184 | { \ | 190 | struct device_attribute *attr, \ |
185 | struct usb_interface *intf = to_usb_interface(dev); \ | 191 | const char *buf, size_t count) \ |
186 | struct interfacekit *kit = usb_get_intfdata(intf); \ | 192 | { \ |
187 | change_string(kit, buf, number - 1); \ | 193 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
188 | return count; \ | 194 | change_string(kit, buf, number - 1); \ |
189 | } \ | 195 | return count; \ |
190 | static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number); | 196 | } |
197 | |||
198 | #define lcd_line_attr(number) \ | ||
199 | __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number) | ||
200 | |||
191 | set_lcd_line(1); | 201 | set_lcd_line(1); |
192 | set_lcd_line(2); | 202 | set_lcd_line(2); |
193 | 203 | ||
194 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 204 | static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
195 | { | 205 | { |
196 | struct usb_interface *intf = to_usb_interface(dev); | 206 | struct interfacekit *kit = dev_get_drvdata(dev); |
197 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
198 | int enabled; | 207 | int enabled; |
199 | unsigned char *buffer; | 208 | unsigned char *buffer; |
200 | int retval = -ENOMEM; | 209 | int retval = -ENOMEM; |
@@ -226,23 +235,30 @@ exit: | |||
226 | kfree(buffer); | 235 | kfree(buffer); |
227 | return retval; | 236 | return retval; |
228 | } | 237 | } |
229 | static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); | 238 | |
239 | static struct device_attribute dev_lcd_line_attrs[] = { | ||
240 | lcd_line_attr(1), | ||
241 | lcd_line_attr(2), | ||
242 | __ATTR(backlight, S_IWUGO, NULL, set_backlight) | ||
243 | }; | ||
230 | 244 | ||
231 | static void remove_lcd_files(struct interfacekit *kit) | 245 | static void remove_lcd_files(struct interfacekit *kit) |
232 | { | 246 | { |
247 | int i; | ||
248 | |||
233 | if (kit->lcd_files_on) { | 249 | if (kit->lcd_files_on) { |
234 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); | 250 | dev_dbg(&kit->udev->dev, "Removing lcd files\n"); |
235 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 251 | |
236 | device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 252 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) |
237 | device_remove_file(&kit->intf->dev, &dev_attr_backlight); | 253 | device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); |
238 | } | 254 | } |
239 | } | 255 | } |
240 | 256 | ||
241 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 257 | static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
242 | { | 258 | { |
243 | struct usb_interface *intf = to_usb_interface(dev); | 259 | struct interfacekit *kit = dev_get_drvdata(dev); |
244 | struct interfacekit *kit = usb_get_intfdata(intf); | ||
245 | int enable; | 260 | int enable; |
261 | int i, rc; | ||
246 | 262 | ||
247 | if (kit->ifkit->has_lcd == 0) | 263 | if (kit->ifkit->has_lcd == 0) |
248 | return -ENODEV; | 264 | return -ENODEV; |
@@ -253,9 +269,12 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
253 | if (enable) { | 269 | if (enable) { |
254 | if (!kit->lcd_files_on) { | 270 | if (!kit->lcd_files_on) { |
255 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); | 271 | dev_dbg(&kit->udev->dev, "Adding lcd files\n"); |
256 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1); | 272 | for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) { |
257 | device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2); | 273 | rc = device_create_file(kit->dev, |
258 | device_create_file(&kit->intf->dev, &dev_attr_backlight); | 274 | &dev_lcd_line_attrs[i]); |
275 | if (rc) | ||
276 | goto out; | ||
277 | } | ||
259 | kit->lcd_files_on = 1; | 278 | kit->lcd_files_on = 1; |
260 | } | 279 | } |
261 | } else { | 280 | } else { |
@@ -266,7 +285,13 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att | |||
266 | } | 285 | } |
267 | 286 | ||
268 | return count; | 287 | return count; |
288 | out: | ||
289 | while (i-- > 0) | ||
290 | device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); | ||
291 | |||
292 | return rc; | ||
269 | } | 293 | } |
294 | |||
270 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); | 295 | static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); |
271 | 296 | ||
272 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) | 297 | static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) |
@@ -362,24 +387,24 @@ static void do_notify(void *data) | |||
362 | for (i=0; i<kit->ifkit->inputs; i++) { | 387 | for (i=0; i<kit->ifkit->inputs; i++) { |
363 | if (test_and_clear_bit(i, &kit->input_events)) { | 388 | if (test_and_clear_bit(i, &kit->input_events)) { |
364 | sprintf(sysfs_file, "input%d", i + 1); | 389 | sprintf(sysfs_file, "input%d", i + 1); |
365 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 390 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
366 | } | 391 | } |
367 | } | 392 | } |
368 | 393 | ||
369 | for (i=0; i<kit->ifkit->sensors; i++) { | 394 | for (i=0; i<kit->ifkit->sensors; i++) { |
370 | if (test_and_clear_bit(i, &kit->sensor_events)) { | 395 | if (test_and_clear_bit(i, &kit->sensor_events)) { |
371 | sprintf(sysfs_file, "sensor%d", i + 1); | 396 | sprintf(sysfs_file, "sensor%d", i + 1); |
372 | sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); | 397 | sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); |
373 | } | 398 | } |
374 | } | 399 | } |
375 | } | 400 | } |
376 | 401 | ||
377 | #define show_set_output(value) \ | 402 | #define show_set_output(value) \ |
378 | static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ | 403 | static ssize_t set_output##value(struct device *dev, \ |
379 | size_t count) \ | 404 | struct device_attribute *attr, \ |
405 | const char *buf, size_t count) \ | ||
380 | { \ | 406 | { \ |
381 | struct usb_interface *intf = to_usb_interface(dev); \ | 407 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
382 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
383 | int enabled; \ | 408 | int enabled; \ |
384 | int retval; \ | 409 | int retval; \ |
385 | \ | 410 | \ |
@@ -391,15 +416,19 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at | |||
391 | return retval ? retval : count; \ | 416 | return retval ? retval : count; \ |
392 | } \ | 417 | } \ |
393 | \ | 418 | \ |
394 | static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 419 | static ssize_t show_output##value(struct device *dev, \ |
420 | struct device_attribute *attr, \ | ||
421 | char *buf) \ | ||
395 | { \ | 422 | { \ |
396 | struct usb_interface *intf = to_usb_interface(dev); \ | 423 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
397 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
398 | \ | 424 | \ |
399 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ | 425 | return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ |
400 | } \ | 426 | } |
401 | static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ | 427 | |
402 | show_output##value, set_output##value); | 428 | #define output_attr(value) \ |
429 | __ATTR(output##value, S_IWUGO | S_IRUGO, \ | ||
430 | show_output##value, set_output##value) | ||
431 | |||
403 | show_set_output(1); | 432 | show_set_output(1); |
404 | show_set_output(2); | 433 | show_set_output(2); |
405 | show_set_output(3); | 434 | show_set_output(3); |
@@ -417,15 +446,24 @@ show_set_output(14); | |||
417 | show_set_output(15); | 446 | show_set_output(15); |
418 | show_set_output(16); | 447 | show_set_output(16); |
419 | 448 | ||
449 | static struct device_attribute dev_output_attrs[] = { | ||
450 | output_attr(1), output_attr(2), output_attr(3), output_attr(4), | ||
451 | output_attr(5), output_attr(6), output_attr(7), output_attr(8), | ||
452 | output_attr(9), output_attr(10), output_attr(11), output_attr(12), | ||
453 | output_attr(13), output_attr(14), output_attr(15), output_attr(16) | ||
454 | }; | ||
455 | |||
420 | #define show_input(value) \ | 456 | #define show_input(value) \ |
421 | static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 457 | static ssize_t show_input##value(struct device *dev, \ |
458 | struct device_attribute *attr, char *buf) \ | ||
422 | { \ | 459 | { \ |
423 | struct usb_interface *intf = to_usb_interface(dev); \ | 460 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
424 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
425 | \ | 461 | \ |
426 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ | 462 | return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ |
427 | } \ | 463 | } |
428 | static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); | 464 | |
465 | #define input_attr(value) \ | ||
466 | __ATTR(input##value, S_IRUGO, show_input##value, NULL) | ||
429 | 467 | ||
430 | show_input(1); | 468 | show_input(1); |
431 | show_input(2); | 469 | show_input(2); |
@@ -444,15 +482,25 @@ show_input(14); | |||
444 | show_input(15); | 482 | show_input(15); |
445 | show_input(16); | 483 | show_input(16); |
446 | 484 | ||
485 | static struct device_attribute dev_input_attrs[] = { | ||
486 | input_attr(1), input_attr(2), input_attr(3), input_attr(4), | ||
487 | input_attr(5), input_attr(6), input_attr(7), input_attr(8), | ||
488 | input_attr(9), input_attr(10), input_attr(11), input_attr(12), | ||
489 | input_attr(13), input_attr(14), input_attr(15), input_attr(16) | ||
490 | }; | ||
491 | |||
447 | #define show_sensor(value) \ | 492 | #define show_sensor(value) \ |
448 | static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ | 493 | static ssize_t show_sensor##value(struct device *dev, \ |
494 | struct device_attribute *attr, \ | ||
495 | char *buf) \ | ||
449 | { \ | 496 | { \ |
450 | struct usb_interface *intf = to_usb_interface(dev); \ | 497 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
451 | struct interfacekit *kit = usb_get_intfdata(intf); \ | ||
452 | \ | 498 | \ |
453 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ | 499 | return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ |
454 | } \ | 500 | } |
455 | static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); | 501 | |
502 | #define sensor_attr(value) \ | ||
503 | __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL) | ||
456 | 504 | ||
457 | show_sensor(1); | 505 | show_sensor(1); |
458 | show_sensor(2); | 506 | show_sensor(2); |
@@ -463,6 +511,11 @@ show_sensor(6); | |||
463 | show_sensor(7); | 511 | show_sensor(7); |
464 | show_sensor(8); | 512 | show_sensor(8); |
465 | 513 | ||
514 | static struct device_attribute dev_sensor_attrs[] = { | ||
515 | sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4), | ||
516 | sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8) | ||
517 | }; | ||
518 | |||
466 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) | 519 | static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) |
467 | { | 520 | { |
468 | struct usb_device *dev = interface_to_usbdev(intf); | 521 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -471,6 +524,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
471 | struct interfacekit *kit; | 524 | struct interfacekit *kit; |
472 | struct driver_interfacekit *ifkit; | 525 | struct driver_interfacekit *ifkit; |
473 | int pipe, maxp, rc = -ENOMEM; | 526 | int pipe, maxp, rc = -ENOMEM; |
527 | int bit, value, i; | ||
474 | 528 | ||
475 | ifkit = (struct driver_interfacekit *)id->driver_info; | 529 | ifkit = (struct driver_interfacekit *)id->driver_info; |
476 | if (!ifkit) | 530 | if (!ifkit) |
@@ -493,6 +547,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
493 | if (!kit) | 547 | if (!kit) |
494 | goto out; | 548 | goto out; |
495 | 549 | ||
550 | kit->dev_no = -1; | ||
496 | kit->ifkit = ifkit; | 551 | kit->ifkit = ifkit; |
497 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); | 552 | kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); |
498 | if (!kit->data) | 553 | if (!kit->data) |
@@ -513,85 +568,80 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
513 | 568 | ||
514 | usb_set_intfdata(intf, kit); | 569 | usb_set_intfdata(intf, kit); |
515 | 570 | ||
571 | do { | ||
572 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | ||
573 | value = test_and_set_bit(bit, &device_no); | ||
574 | } while(value); | ||
575 | kit->dev_no = bit; | ||
576 | |||
577 | kit->dev = device_create(phidget_class, &kit->udev->dev, 0, | ||
578 | "interfacekit%d", kit->dev_no); | ||
579 | if (IS_ERR(kit->dev)) { | ||
580 | rc = PTR_ERR(kit->dev); | ||
581 | kit->dev = NULL; | ||
582 | goto out; | ||
583 | } | ||
584 | dev_set_drvdata(kit->dev, kit); | ||
585 | |||
516 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { | 586 | if (usb_submit_urb(kit->irq, GFP_KERNEL)) { |
517 | rc = -EIO; | 587 | rc = -EIO; |
518 | goto out; | 588 | goto out; |
519 | } | 589 | } |
520 | 590 | ||
521 | if (ifkit->outputs >= 4) { | 591 | for (i=0; i<ifkit->outputs; i++ ) { |
522 | device_create_file(&intf->dev, &dev_attr_output1); | 592 | rc = device_create_file(kit->dev, &dev_output_attrs[i]); |
523 | device_create_file(&intf->dev, &dev_attr_output2); | 593 | if (rc) |
524 | device_create_file(&intf->dev, &dev_attr_output3); | 594 | goto out2; |
525 | device_create_file(&intf->dev, &dev_attr_output4); | ||
526 | } | ||
527 | if (ifkit->outputs >= 8) { | ||
528 | device_create_file(&intf->dev, &dev_attr_output5); | ||
529 | device_create_file(&intf->dev, &dev_attr_output6); | ||
530 | device_create_file(&intf->dev, &dev_attr_output7); | ||
531 | device_create_file(&intf->dev, &dev_attr_output8); | ||
532 | } | ||
533 | if (ifkit->outputs == 16) { | ||
534 | device_create_file(&intf->dev, &dev_attr_output9); | ||
535 | device_create_file(&intf->dev, &dev_attr_output10); | ||
536 | device_create_file(&intf->dev, &dev_attr_output11); | ||
537 | device_create_file(&intf->dev, &dev_attr_output12); | ||
538 | device_create_file(&intf->dev, &dev_attr_output13); | ||
539 | device_create_file(&intf->dev, &dev_attr_output14); | ||
540 | device_create_file(&intf->dev, &dev_attr_output15); | ||
541 | device_create_file(&intf->dev, &dev_attr_output16); | ||
542 | } | 595 | } |
543 | 596 | ||
544 | if (ifkit->inputs >= 4) { | 597 | for (i=0; i<ifkit->inputs; i++ ) { |
545 | device_create_file(&intf->dev, &dev_attr_input1); | 598 | rc = device_create_file(kit->dev, &dev_input_attrs[i]); |
546 | device_create_file(&intf->dev, &dev_attr_input2); | 599 | if (rc) |
547 | device_create_file(&intf->dev, &dev_attr_input3); | 600 | goto out3; |
548 | device_create_file(&intf->dev, &dev_attr_input4); | ||
549 | } | ||
550 | if (ifkit->inputs >= 8) { | ||
551 | device_create_file(&intf->dev, &dev_attr_input5); | ||
552 | device_create_file(&intf->dev, &dev_attr_input6); | ||
553 | device_create_file(&intf->dev, &dev_attr_input7); | ||
554 | device_create_file(&intf->dev, &dev_attr_input8); | ||
555 | } | ||
556 | if (ifkit->inputs == 16) { | ||
557 | device_create_file(&intf->dev, &dev_attr_input9); | ||
558 | device_create_file(&intf->dev, &dev_attr_input10); | ||
559 | device_create_file(&intf->dev, &dev_attr_input11); | ||
560 | device_create_file(&intf->dev, &dev_attr_input12); | ||
561 | device_create_file(&intf->dev, &dev_attr_input13); | ||
562 | device_create_file(&intf->dev, &dev_attr_input14); | ||
563 | device_create_file(&intf->dev, &dev_attr_input15); | ||
564 | device_create_file(&intf->dev, &dev_attr_input16); | ||
565 | } | 601 | } |
566 | 602 | ||
567 | if (ifkit->sensors >= 4) { | 603 | for (i=0; i<ifkit->sensors; i++ ) { |
568 | device_create_file(&intf->dev, &dev_attr_sensor1); | 604 | rc = device_create_file(kit->dev, &dev_sensor_attrs[i]); |
569 | device_create_file(&intf->dev, &dev_attr_sensor2); | 605 | if (rc) |
570 | device_create_file(&intf->dev, &dev_attr_sensor3); | 606 | goto out4; |
571 | device_create_file(&intf->dev, &dev_attr_sensor4); | ||
572 | } | ||
573 | if (ifkit->sensors >= 7) { | ||
574 | device_create_file(&intf->dev, &dev_attr_sensor5); | ||
575 | device_create_file(&intf->dev, &dev_attr_sensor6); | ||
576 | device_create_file(&intf->dev, &dev_attr_sensor7); | ||
577 | } | 607 | } |
578 | if (ifkit->sensors == 8) | ||
579 | device_create_file(&intf->dev, &dev_attr_sensor8); | ||
580 | 608 | ||
581 | if (ifkit->has_lcd) | 609 | if (ifkit->has_lcd) { |
582 | device_create_file(&intf->dev, &dev_attr_lcd); | 610 | rc = device_create_file(kit->dev, &dev_attr_lcd); |
611 | if (rc) | ||
612 | goto out4; | ||
613 | |||
614 | } | ||
583 | 615 | ||
584 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", | 616 | dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", |
585 | ifkit->sensors, ifkit->inputs, ifkit->outputs); | 617 | ifkit->sensors, ifkit->inputs, ifkit->outputs); |
586 | 618 | ||
587 | return 0; | 619 | return 0; |
588 | 620 | ||
621 | out4: | ||
622 | while (i-- > 0) | ||
623 | device_remove_file(kit->dev, &dev_sensor_attrs[i]); | ||
624 | |||
625 | i = ifkit->inputs; | ||
626 | out3: | ||
627 | while (i-- > 0) | ||
628 | device_remove_file(kit->dev, &dev_input_attrs[i]); | ||
629 | |||
630 | i = ifkit->outputs; | ||
631 | out2: | ||
632 | while (i-- > 0) | ||
633 | device_remove_file(kit->dev, &dev_output_attrs[i]); | ||
589 | out: | 634 | out: |
590 | if (kit) { | 635 | if (kit) { |
591 | if (kit->irq) | 636 | if (kit->irq) |
592 | usb_free_urb(kit->irq); | 637 | usb_free_urb(kit->irq); |
593 | if (kit->data) | 638 | if (kit->data) |
594 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); | 639 | usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); |
640 | if (kit->dev) | ||
641 | device_unregister(kit->dev); | ||
642 | if (kit->dev_no >= 0) | ||
643 | clear_bit(kit->dev_no, &device_no); | ||
644 | |||
595 | kfree(kit); | 645 | kfree(kit); |
596 | } | 646 | } |
597 | 647 | ||
@@ -601,6 +651,7 @@ out: | |||
601 | static void interfacekit_disconnect(struct usb_interface *interface) | 651 | static void interfacekit_disconnect(struct usb_interface *interface) |
602 | { | 652 | { |
603 | struct interfacekit *kit; | 653 | struct interfacekit *kit; |
654 | int i; | ||
604 | 655 | ||
605 | kit = usb_get_intfdata(interface); | 656 | kit = usb_get_intfdata(interface); |
606 | usb_set_intfdata(interface, NULL); | 657 | usb_set_intfdata(interface, NULL); |
@@ -613,73 +664,28 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
613 | 664 | ||
614 | cancel_delayed_work(&kit->do_notify); | 665 | cancel_delayed_work(&kit->do_notify); |
615 | 666 | ||
616 | if (kit->ifkit->outputs >= 4) { | 667 | for (i=0; i<kit->ifkit->outputs; i++) |
617 | device_remove_file(&interface->dev, &dev_attr_output1); | 668 | device_remove_file(kit->dev, &dev_output_attrs[i]); |
618 | device_remove_file(&interface->dev, &dev_attr_output2); | ||
619 | device_remove_file(&interface->dev, &dev_attr_output3); | ||
620 | device_remove_file(&interface->dev, &dev_attr_output4); | ||
621 | } | ||
622 | if (kit->ifkit->outputs >= 8) { | ||
623 | device_remove_file(&interface->dev, &dev_attr_output5); | ||
624 | device_remove_file(&interface->dev, &dev_attr_output6); | ||
625 | device_remove_file(&interface->dev, &dev_attr_output7); | ||
626 | device_remove_file(&interface->dev, &dev_attr_output8); | ||
627 | } | ||
628 | if (kit->ifkit->outputs == 16) { | ||
629 | device_remove_file(&interface->dev, &dev_attr_output9); | ||
630 | device_remove_file(&interface->dev, &dev_attr_output10); | ||
631 | device_remove_file(&interface->dev, &dev_attr_output11); | ||
632 | device_remove_file(&interface->dev, &dev_attr_output12); | ||
633 | device_remove_file(&interface->dev, &dev_attr_output13); | ||
634 | device_remove_file(&interface->dev, &dev_attr_output14); | ||
635 | device_remove_file(&interface->dev, &dev_attr_output15); | ||
636 | device_remove_file(&interface->dev, &dev_attr_output16); | ||
637 | } | ||
638 | 669 | ||
639 | if (kit->ifkit->inputs >= 4) { | 670 | for (i=0; i<kit->ifkit->inputs; i++) |
640 | device_remove_file(&interface->dev, &dev_attr_input1); | 671 | device_remove_file(kit->dev, &dev_input_attrs[i]); |
641 | device_remove_file(&interface->dev, &dev_attr_input2); | ||
642 | device_remove_file(&interface->dev, &dev_attr_input3); | ||
643 | device_remove_file(&interface->dev, &dev_attr_input4); | ||
644 | } | ||
645 | if (kit->ifkit->inputs >= 8) { | ||
646 | device_remove_file(&interface->dev, &dev_attr_input5); | ||
647 | device_remove_file(&interface->dev, &dev_attr_input6); | ||
648 | device_remove_file(&interface->dev, &dev_attr_input7); | ||
649 | device_remove_file(&interface->dev, &dev_attr_input8); | ||
650 | } | ||
651 | if (kit->ifkit->inputs == 16) { | ||
652 | device_remove_file(&interface->dev, &dev_attr_input9); | ||
653 | device_remove_file(&interface->dev, &dev_attr_input10); | ||
654 | device_remove_file(&interface->dev, &dev_attr_input11); | ||
655 | device_remove_file(&interface->dev, &dev_attr_input12); | ||
656 | device_remove_file(&interface->dev, &dev_attr_input13); | ||
657 | device_remove_file(&interface->dev, &dev_attr_input14); | ||
658 | device_remove_file(&interface->dev, &dev_attr_input15); | ||
659 | device_remove_file(&interface->dev, &dev_attr_input16); | ||
660 | } | ||
661 | 672 | ||
662 | if (kit->ifkit->sensors >= 4) { | 673 | for (i=0; i<kit->ifkit->sensors; i++) |
663 | device_remove_file(&interface->dev, &dev_attr_sensor1); | 674 | device_remove_file(kit->dev, &dev_sensor_attrs[i]); |
664 | device_remove_file(&interface->dev, &dev_attr_sensor2); | 675 | |
665 | device_remove_file(&interface->dev, &dev_attr_sensor3); | 676 | if (kit->ifkit->has_lcd) { |
666 | device_remove_file(&interface->dev, &dev_attr_sensor4); | 677 | device_remove_file(kit->dev, &dev_attr_lcd); |
667 | } | 678 | remove_lcd_files(kit); |
668 | if (kit->ifkit->sensors >= 7) { | ||
669 | device_remove_file(&interface->dev, &dev_attr_sensor5); | ||
670 | device_remove_file(&interface->dev, &dev_attr_sensor6); | ||
671 | device_remove_file(&interface->dev, &dev_attr_sensor7); | ||
672 | } | 679 | } |
673 | if (kit->ifkit->sensors == 8) | ||
674 | device_remove_file(&interface->dev, &dev_attr_sensor8); | ||
675 | 680 | ||
676 | if (kit->ifkit->has_lcd) | 681 | device_unregister(kit->dev); |
677 | device_remove_file(&interface->dev, &dev_attr_lcd); | ||
678 | 682 | ||
679 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", | 683 | dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", |
680 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); | 684 | kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); |
681 | 685 | ||
682 | usb_put_dev(kit->udev); | 686 | usb_put_dev(kit->udev); |
687 | clear_bit(kit->dev_no, &device_no); | ||
688 | |||
683 | kfree(kit); | 689 | kfree(kit); |
684 | } | 690 | } |
685 | 691 | ||
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c new file mode 100644 index 000000000000..6b59b620d616 --- /dev/null +++ b/drivers/usb/misc/phidgetmotorcontrol.c | |||
@@ -0,0 +1,466 @@ | |||
1 | /* | ||
2 | * USB Phidget MotorControl driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Sean Young <sean@mess.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/usb.h> | ||
17 | |||
18 | #include "phidget.h" | ||
19 | |||
20 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | ||
21 | #define DRIVER_DESC "USB PhidgetMotorControl Driver" | ||
22 | |||
23 | #define USB_VENDOR_ID_GLAB 0x06c2 | ||
24 | #define USB_DEVICE_ID_MOTORCONTROL 0x0058 | ||
25 | |||
26 | #define URB_INT_SIZE 8 | ||
27 | |||
28 | static unsigned long device_no; | ||
29 | |||
30 | struct motorcontrol { | ||
31 | struct usb_device *udev; | ||
32 | struct usb_interface *intf; | ||
33 | struct device *dev; | ||
34 | int dev_no; | ||
35 | u8 inputs[4]; | ||
36 | s8 desired_speed[2]; | ||
37 | s8 speed[2]; | ||
38 | s16 _current[2]; | ||
39 | s8 acceleration[2]; | ||
40 | struct urb *irq; | ||
41 | unsigned char *data; | ||
42 | dma_addr_t data_dma; | ||
43 | |||
44 | struct work_struct do_notify; | ||
45 | unsigned long input_events; | ||
46 | unsigned long speed_events; | ||
47 | unsigned long exceed_events; | ||
48 | }; | ||
49 | |||
50 | static struct usb_device_id id_table[] = { | ||
51 | { USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) }, | ||
52 | {} | ||
53 | }; | ||
54 | MODULE_DEVICE_TABLE(usb, id_table); | ||
55 | |||
56 | static int set_motor(struct motorcontrol *mc, int motor) | ||
57 | { | ||
58 | u8 *buffer; | ||
59 | int speed, speed2, acceleration; | ||
60 | int retval; | ||
61 | |||
62 | buffer = kzalloc(8, GFP_KERNEL); | ||
63 | if (!buffer) { | ||
64 | dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__); | ||
65 | return -ENOMEM; | ||
66 | } | ||
67 | |||
68 | acceleration = mc->acceleration[motor] * 10; | ||
69 | /* -127 <= speed <= 127 */ | ||
70 | speed = (mc->desired_speed[motor] * 127) / 100; | ||
71 | /* -0x7300 <= speed2 <= 0x7300 */ | ||
72 | speed2 = (mc->desired_speed[motor] * 230 * 128) / 100; | ||
73 | |||
74 | buffer[0] = motor; | ||
75 | buffer[1] = speed; | ||
76 | buffer[2] = acceleration >> 8; | ||
77 | buffer[3] = acceleration; | ||
78 | buffer[4] = speed2 >> 8; | ||
79 | buffer[5] = speed2; | ||
80 | |||
81 | retval = usb_control_msg(mc->udev, | ||
82 | usb_sndctrlpipe(mc->udev, 0), | ||
83 | 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); | ||
84 | |||
85 | if (retval != 8) | ||
86 | dev_err(&mc->intf->dev, "usb_control_msg returned %d\n", | ||
87 | retval); | ||
88 | kfree(buffer); | ||
89 | |||
90 | return retval < 0 ? retval : 0; | ||
91 | } | ||
92 | |||
93 | static void motorcontrol_irq(struct urb *urb, struct pt_regs *regs) | ||
94 | { | ||
95 | struct motorcontrol *mc = urb->context; | ||
96 | unsigned char *buffer = mc->data; | ||
97 | int i, level; | ||
98 | int status; | ||
99 | |||
100 | switch (urb->status) { | ||
101 | case 0: /* success */ | ||
102 | break; | ||
103 | case -ECONNRESET: /* unlink */ | ||
104 | case -ENOENT: | ||
105 | case -ESHUTDOWN: | ||
106 | return; | ||
107 | /* -EPIPE: should clear the halt */ | ||
108 | default: /* error */ | ||
109 | goto resubmit; | ||
110 | } | ||
111 | |||
112 | /* digital inputs */ | ||
113 | for (i=0; i<4; i++) { | ||
114 | level = (buffer[0] >> i) & 1; | ||
115 | if (mc->inputs[i] != level) { | ||
116 | mc->inputs[i] = level; | ||
117 | set_bit(i, &mc->input_events); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /* motor speed */ | ||
122 | if (buffer[2] == 0) { | ||
123 | for (i=0; i<2; i++) { | ||
124 | level = ((s8)buffer[4+i]) * 100 / 127; | ||
125 | if (mc->speed[i] != level) { | ||
126 | mc->speed[i] = level; | ||
127 | set_bit(i, &mc->speed_events); | ||
128 | } | ||
129 | } | ||
130 | } else { | ||
131 | int index = buffer[3] & 1; | ||
132 | |||
133 | level = ((s8)buffer[4] << 8) | buffer[5]; | ||
134 | level = level * 100 / 29440; | ||
135 | if (mc->speed[index] != level) { | ||
136 | mc->speed[index] = level; | ||
137 | set_bit(index, &mc->speed_events); | ||
138 | } | ||
139 | |||
140 | level = ((s8)buffer[6] << 8) | buffer[7]; | ||
141 | mc->_current[index] = level * 100 / 1572; | ||
142 | } | ||
143 | |||
144 | if (buffer[1] & 1) | ||
145 | set_bit(0, &mc->exceed_events); | ||
146 | |||
147 | if (buffer[1] & 2) | ||
148 | set_bit(1, &mc->exceed_events); | ||
149 | |||
150 | if (mc->input_events || mc->exceed_events || mc->speed_events) | ||
151 | schedule_work(&mc->do_notify); | ||
152 | |||
153 | resubmit: | ||
154 | status = usb_submit_urb(urb, SLAB_ATOMIC); | ||
155 | if (status) | ||
156 | dev_err(&mc->intf->dev, | ||
157 | "can't resubmit intr, %s-%s/motorcontrol0, status %d", | ||
158 | mc->udev->bus->bus_name, | ||
159 | mc->udev->devpath, status); | ||
160 | } | ||
161 | |||
162 | static void do_notify(void *data) | ||
163 | { | ||
164 | struct motorcontrol *mc = data; | ||
165 | int i; | ||
166 | char sysfs_file[8]; | ||
167 | |||
168 | for (i=0; i<4; i++) { | ||
169 | if (test_and_clear_bit(i, &mc->input_events)) { | ||
170 | sprintf(sysfs_file, "input%d", i); | ||
171 | sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | for (i=0; i<2; i++) { | ||
176 | if (test_and_clear_bit(i, &mc->speed_events)) { | ||
177 | sprintf(sysfs_file, "speed%d", i); | ||
178 | sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | for (i=0; i<2; i++) { | ||
183 | if (test_and_clear_bit(i, &mc->exceed_events)) | ||
184 | dev_warn(&mc->intf->dev, | ||
185 | "motor #%d exceeds 1.5 Amp current limit\n", i); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | #define show_set_speed(value) \ | ||
190 | static ssize_t set_speed##value(struct device *dev, \ | ||
191 | struct device_attribute *attr, \ | ||
192 | const char *buf, size_t count) \ | ||
193 | { \ | ||
194 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | ||
195 | int speed; \ | ||
196 | int retval; \ | ||
197 | \ | ||
198 | if (sscanf(buf, "%d", &speed) < 1) \ | ||
199 | return -EINVAL; \ | ||
200 | \ | ||
201 | if (speed < -100 || speed > 100) \ | ||
202 | return -EINVAL; \ | ||
203 | \ | ||
204 | mc->desired_speed[value] = speed; \ | ||
205 | \ | ||
206 | retval = set_motor(mc, value); \ | ||
207 | \ | ||
208 | return retval ? retval : count; \ | ||
209 | } \ | ||
210 | \ | ||
211 | static ssize_t show_speed##value(struct device *dev, \ | ||
212 | struct device_attribute *attr, \ | ||
213 | char *buf) \ | ||
214 | { \ | ||
215 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | ||
216 | \ | ||
217 | return sprintf(buf, "%d\n", mc->speed[value]); \ | ||
218 | } | ||
219 | |||
220 | #define speed_attr(value) \ | ||
221 | __ATTR(speed##value, S_IWUGO | S_IRUGO, \ | ||
222 | show_speed##value, set_speed##value) | ||
223 | |||
224 | show_set_speed(0); | ||
225 | show_set_speed(1); | ||
226 | |||
227 | #define show_set_acceleration(value) \ | ||
228 | static ssize_t set_acceleration##value(struct device *dev, \ | ||
229 | struct device_attribute *attr, \ | ||
230 | const char *buf, size_t count) \ | ||
231 | { \ | ||
232 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | ||
233 | int acceleration; \ | ||
234 | int retval; \ | ||
235 | \ | ||
236 | if (sscanf(buf, "%d", &acceleration) < 1) \ | ||
237 | return -EINVAL; \ | ||
238 | \ | ||
239 | if (acceleration < 0 || acceleration > 100) \ | ||
240 | return -EINVAL; \ | ||
241 | \ | ||
242 | mc->acceleration[value] = acceleration; \ | ||
243 | \ | ||
244 | retval = set_motor(mc, value); \ | ||
245 | \ | ||
246 | return retval ? retval : count; \ | ||
247 | } \ | ||
248 | \ | ||
249 | static ssize_t show_acceleration##value(struct device *dev, \ | ||
250 | struct device_attribute *attr, \ | ||
251 | char *buf) \ | ||
252 | { \ | ||
253 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | ||
254 | \ | ||
255 | return sprintf(buf, "%d\n", mc->acceleration[value]); \ | ||
256 | } | ||
257 | |||
258 | #define acceleration_attr(value) \ | ||
259 | __ATTR(acceleration##value, S_IWUGO | S_IRUGO, \ | ||
260 | show_acceleration##value, set_acceleration##value) | ||
261 | |||
262 | show_set_acceleration(0); | ||
263 | show_set_acceleration(1); | ||
264 | |||
265 | #define show_current(value) \ | ||
266 | static ssize_t show_current##value(struct device *dev, \ | ||
267 | struct device_attribute *attr, \ | ||
268 | char *buf) \ | ||
269 | { \ | ||
270 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | ||
271 | \ | ||
272 | return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ | ||
273 | } | ||
274 | |||
275 | #define current_attr(value) \ | ||
276 | __ATTR(current##value, S_IRUGO, show_current##value, NULL) | ||
277 | |||
278 | show_current(0); | ||
279 | show_current(1); | ||
280 | |||
281 | #define show_input(value) \ | ||
282 | static ssize_t show_input##value(struct device *dev, \ | ||
283 | struct device_attribute *attr, \ | ||
284 | char *buf) \ | ||
285 | { \ | ||
286 | struct motorcontrol *mc = dev_get_drvdata(dev); \ | ||
287 | \ | ||
288 | return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ | ||
289 | } | ||
290 | |||
291 | #define input_attr(value) \ | ||
292 | __ATTR(input##value, S_IRUGO, show_input##value, NULL) | ||
293 | |||
294 | show_input(0); | ||
295 | show_input(1); | ||
296 | show_input(2); | ||
297 | show_input(3); | ||
298 | |||
299 | static struct device_attribute dev_attrs[] = { | ||
300 | input_attr(0), | ||
301 | input_attr(1), | ||
302 | input_attr(2), | ||
303 | input_attr(3), | ||
304 | speed_attr(0), | ||
305 | speed_attr(1), | ||
306 | acceleration_attr(0), | ||
307 | acceleration_attr(1), | ||
308 | current_attr(0), | ||
309 | current_attr(1) | ||
310 | }; | ||
311 | |||
312 | static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
313 | { | ||
314 | struct usb_device *dev = interface_to_usbdev(intf); | ||
315 | struct usb_host_interface *interface; | ||
316 | struct usb_endpoint_descriptor *endpoint; | ||
317 | struct motorcontrol *mc; | ||
318 | int pipe, maxp, rc = -ENOMEM; | ||
319 | int bit, value, i; | ||
320 | |||
321 | interface = intf->cur_altsetting; | ||
322 | if (interface->desc.bNumEndpoints != 1) | ||
323 | return -ENODEV; | ||
324 | |||
325 | endpoint = &interface->endpoint[0].desc; | ||
326 | if (!(endpoint->bEndpointAddress & 0x80)) | ||
327 | return -ENODEV; | ||
328 | |||
329 | /* | ||
330 | * bmAttributes | ||
331 | */ | ||
332 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
333 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
334 | |||
335 | mc = kzalloc(sizeof(*mc), GFP_KERNEL); | ||
336 | if (!mc) | ||
337 | goto out; | ||
338 | |||
339 | mc->dev_no = -1; | ||
340 | mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma); | ||
341 | if (!mc->data) | ||
342 | goto out; | ||
343 | |||
344 | mc->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
345 | if (!mc->irq) | ||
346 | goto out; | ||
347 | |||
348 | mc->udev = usb_get_dev(dev); | ||
349 | mc->intf = intf; | ||
350 | mc->acceleration[0] = mc->acceleration[1] = 10; | ||
351 | INIT_WORK(&mc->do_notify, do_notify, mc); | ||
352 | usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data, | ||
353 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, | ||
354 | motorcontrol_irq, mc, endpoint->bInterval); | ||
355 | mc->irq->transfer_dma = mc->data_dma; | ||
356 | mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
357 | |||
358 | usb_set_intfdata(intf, mc); | ||
359 | |||
360 | do { | ||
361 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); | ||
362 | value = test_and_set_bit(bit, &device_no); | ||
363 | } while(value); | ||
364 | mc->dev_no = bit; | ||
365 | |||
366 | mc->dev = device_create(phidget_class, &mc->udev->dev, 0, | ||
367 | "motorcontrol%d", mc->dev_no); | ||
368 | if (IS_ERR(mc->dev)) { | ||
369 | rc = PTR_ERR(mc->dev); | ||
370 | mc->dev = NULL; | ||
371 | goto out; | ||
372 | } | ||
373 | |||
374 | dev_set_drvdata(mc->dev, mc); | ||
375 | |||
376 | if (usb_submit_urb(mc->irq, GFP_KERNEL)) { | ||
377 | rc = -EIO; | ||
378 | goto out; | ||
379 | } | ||
380 | |||
381 | for (i=0; i<ARRAY_SIZE(dev_attrs); i++) { | ||
382 | rc = device_create_file(mc->dev, &dev_attrs[i]); | ||
383 | if (rc) | ||
384 | goto out2; | ||
385 | } | ||
386 | |||
387 | dev_info(&intf->dev, "USB PhidgetMotorControl attached\n"); | ||
388 | |||
389 | return 0; | ||
390 | out2: | ||
391 | while (i-- > 0) | ||
392 | device_remove_file(mc->dev, &dev_attrs[i]); | ||
393 | out: | ||
394 | if (mc) { | ||
395 | if (mc->irq) | ||
396 | usb_free_urb(mc->irq); | ||
397 | if (mc->data) | ||
398 | usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); | ||
399 | if (mc->dev) | ||
400 | device_unregister(mc->dev); | ||
401 | if (mc->dev_no >= 0) | ||
402 | clear_bit(mc->dev_no, &device_no); | ||
403 | |||
404 | kfree(mc); | ||
405 | } | ||
406 | |||
407 | return rc; | ||
408 | } | ||
409 | |||
410 | static void motorcontrol_disconnect(struct usb_interface *interface) | ||
411 | { | ||
412 | struct motorcontrol *mc; | ||
413 | int i; | ||
414 | |||
415 | mc = usb_get_intfdata(interface); | ||
416 | usb_set_intfdata(interface, NULL); | ||
417 | if (!mc) | ||
418 | return; | ||
419 | |||
420 | usb_kill_urb(mc->irq); | ||
421 | usb_free_urb(mc->irq); | ||
422 | usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma); | ||
423 | |||
424 | cancel_delayed_work(&mc->do_notify); | ||
425 | |||
426 | for (i=0; i<ARRAY_SIZE(dev_attrs); i++) | ||
427 | device_remove_file(mc->dev, &dev_attrs[i]); | ||
428 | |||
429 | device_unregister(mc->dev); | ||
430 | |||
431 | usb_put_dev(mc->udev); | ||
432 | clear_bit(mc->dev_no, &device_no); | ||
433 | kfree(mc); | ||
434 | |||
435 | dev_info(&interface->dev, "USB PhidgetMotorControl detached\n"); | ||
436 | } | ||
437 | |||
438 | static struct usb_driver motorcontrol_driver = { | ||
439 | .name = "phidgetmotorcontrol", | ||
440 | .probe = motorcontrol_probe, | ||
441 | .disconnect = motorcontrol_disconnect, | ||
442 | .id_table = id_table | ||
443 | }; | ||
444 | |||
445 | static int __init motorcontrol_init(void) | ||
446 | { | ||
447 | int retval = 0; | ||
448 | |||
449 | retval = usb_register(&motorcontrol_driver); | ||
450 | if (retval) | ||
451 | err("usb_register failed. Error number %d", retval); | ||
452 | |||
453 | return retval; | ||
454 | } | ||
455 | |||
456 | static void __exit motorcontrol_exit(void) | ||
457 | { | ||
458 | usb_deregister(&motorcontrol_driver); | ||
459 | } | ||
460 | |||
461 | module_init(motorcontrol_init); | ||
462 | module_exit(motorcontrol_exit); | ||
463 | |||
464 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
465 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
466 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index c0df79c96538..7163f05c5b27 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * USB PhidgetServo driver 1.0 | 2 | * USB PhidgetServo driver 1.0 |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Sean Young <sean@mess.org> | 4 | * Copyright (C) 2004, 2006 Sean Young <sean@mess.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -15,14 +15,6 @@ | |||
15 | * | 15 | * |
16 | * CAUTION: Generally you should use 0 < degrees < 180 as anything else | 16 | * CAUTION: Generally you should use 0 < degrees < 180 as anything else |
17 | * is probably beyond the range of your servo and may damage it. | 17 | * is probably beyond the range of your servo and may damage it. |
18 | * | ||
19 | * Jun 16, 2004: Sean Young <sean@mess.org> | ||
20 | * - cleanups | ||
21 | * - was using memory after kfree() | ||
22 | * Aug 8, 2004: Sean Young <sean@mess.org> | ||
23 | * - set the highest angle as high as the hardware allows, there are | ||
24 | * some odd servos out there | ||
25 | * | ||
26 | */ | 18 | */ |
27 | 19 | ||
28 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
@@ -32,6 +24,8 @@ | |||
32 | #include <linux/module.h> | 24 | #include <linux/module.h> |
33 | #include <linux/usb.h> | 25 | #include <linux/usb.h> |
34 | 26 | ||
27 | #include "phidget.h" | ||
28 | |||
35 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" | 29 | #define DRIVER_AUTHOR "Sean Young <sean@mess.org>" |
36 | #define DRIVER_DESC "USB PhidgetServo Driver" | 30 | #define DRIVER_DESC "USB PhidgetServo Driver" |
37 | 31 | ||
@@ -70,8 +64,12 @@ static struct usb_device_id id_table[] = { | |||
70 | 64 | ||
71 | MODULE_DEVICE_TABLE(usb, id_table); | 65 | MODULE_DEVICE_TABLE(usb, id_table); |
72 | 66 | ||
67 | static int unsigned long device_no; | ||
68 | |||
73 | struct phidget_servo { | 69 | struct phidget_servo { |
74 | struct usb_device *udev; | 70 | struct usb_device *udev; |
71 | struct device *dev; | ||
72 | int dev_no; | ||
75 | ulong type; | 73 | ulong type; |
76 | int pulse[4]; | 74 | int pulse[4]; |
77 | int degrees[4]; | 75 | int degrees[4]; |
@@ -203,16 +201,16 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, | |||
203 | } | 201 | } |
204 | 202 | ||
205 | #define show_set(value) \ | 203 | #define show_set(value) \ |
206 | static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr, \ | 204 | static ssize_t set_servo##value (struct device *dev, \ |
205 | struct device_attribute *attr, \ | ||
207 | const char *buf, size_t count) \ | 206 | const char *buf, size_t count) \ |
208 | { \ | 207 | { \ |
209 | int degrees, minutes, retval; \ | 208 | int degrees, minutes, retval; \ |
210 | struct usb_interface *intf = to_usb_interface (dev); \ | 209 | struct phidget_servo *servo = dev_get_drvdata(dev); \ |
211 | struct phidget_servo *servo = usb_get_intfdata (intf); \ | ||
212 | \ | 210 | \ |
213 | minutes = 0; \ | 211 | minutes = 0; \ |
214 | /* must at least convert degrees */ \ | 212 | /* must at least convert degrees */ \ |
215 | if (sscanf (buf, "%d.%d", °rees, &minutes) < 1) { \ | 213 | if (sscanf(buf, "%d.%d", °rees, &minutes) < 1) { \ |
216 | return -EINVAL; \ | 214 | return -EINVAL; \ |
217 | } \ | 215 | } \ |
218 | \ | 216 | \ |
@@ -220,86 +218,127 @@ static ssize_t set_servo##value (struct device *dev, struct device_attribute *at | |||
220 | return -EINVAL; \ | 218 | return -EINVAL; \ |
221 | \ | 219 | \ |
222 | if (servo->type & SERVO_VERSION_30) \ | 220 | if (servo->type & SERVO_VERSION_30) \ |
223 | retval = change_position_v30 (servo, value, degrees, \ | 221 | retval = change_position_v30(servo, value, degrees, \ |
224 | minutes); \ | 222 | minutes); \ |
225 | else \ | 223 | else \ |
226 | retval = change_position_v20 (servo, value, degrees, \ | 224 | retval = change_position_v20(servo, value, degrees, \ |
227 | minutes); \ | 225 | minutes); \ |
228 | \ | 226 | \ |
229 | return retval < 0 ? retval : count; \ | 227 | return retval < 0 ? retval : count; \ |
230 | } \ | 228 | } \ |
231 | \ | 229 | \ |
232 | static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf) \ | 230 | static ssize_t show_servo##value (struct device *dev, \ |
231 | struct device_attribute *attr, \ | ||
232 | char *buf) \ | ||
233 | { \ | 233 | { \ |
234 | struct usb_interface *intf = to_usb_interface (dev); \ | 234 | struct phidget_servo *servo = dev_get_drvdata(dev); \ |
235 | struct phidget_servo *servo = usb_get_intfdata (intf); \ | ||
236 | \ | 235 | \ |
237 | return sprintf (buf, "%d.%02d\n", servo->degrees[value], \ | 236 | return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ |
238 | servo->minutes[value]); \ | 237 | servo->minutes[value]); \ |
239 | } \ | 238 | } |
240 | static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO, \ | ||
241 | show_servo##value, set_servo##value); | ||
242 | 239 | ||
240 | #define servo_attr(value) \ | ||
241 | __ATTR(servo##value, S_IWUGO | S_IRUGO, \ | ||
242 | show_servo##value, set_servo##value) | ||
243 | show_set(0); | 243 | show_set(0); |
244 | show_set(1); | 244 | show_set(1); |
245 | show_set(2); | 245 | show_set(2); |
246 | show_set(3); | 246 | show_set(3); |
247 | 247 | ||
248 | static struct device_attribute dev_attrs[] = { | ||
249 | servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3) | ||
250 | }; | ||
251 | |||
248 | static int | 252 | static int |
249 | servo_probe(struct usb_interface *interface, const struct usb_device_id *id) | 253 | servo_probe(struct usb_interface *interface, const struct usb_device_id *id) |
250 | { | 254 | { |
251 | struct usb_device *udev = interface_to_usbdev(interface); | 255 | struct usb_device *udev = interface_to_usbdev(interface); |
252 | struct phidget_servo *dev; | 256 | struct phidget_servo *dev; |
257 | int bit, value, rc; | ||
258 | int servo_count, i; | ||
253 | 259 | ||
254 | dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); | 260 | dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); |
255 | if (dev == NULL) { | 261 | if (dev == NULL) { |
256 | dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); | 262 | dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); |
257 | return -ENOMEM; | 263 | rc = -ENOMEM; |
264 | goto out; | ||
258 | } | 265 | } |
259 | 266 | ||
260 | dev->udev = usb_get_dev(udev); | 267 | dev->udev = usb_get_dev(udev); |
261 | dev->type = id->driver_info; | 268 | dev->type = id->driver_info; |
269 | dev->dev_no = -1; | ||
262 | usb_set_intfdata(interface, dev); | 270 | usb_set_intfdata(interface, dev); |
263 | 271 | ||
264 | device_create_file(&interface->dev, &dev_attr_servo0); | 272 | do { |
265 | if (dev->type & SERVO_COUNT_QUAD) { | 273 | bit = find_first_zero_bit(&device_no, sizeof(device_no)); |
266 | device_create_file(&interface->dev, &dev_attr_servo1); | 274 | value = test_and_set_bit(bit, &device_no); |
267 | device_create_file(&interface->dev, &dev_attr_servo2); | 275 | } while (value); |
268 | device_create_file(&interface->dev, &dev_attr_servo3); | 276 | dev->dev_no = bit; |
277 | |||
278 | dev->dev = device_create(phidget_class, &dev->udev->dev, 0, | ||
279 | "servo%d", dev->dev_no); | ||
280 | if (IS_ERR(dev->dev)) { | ||
281 | rc = PTR_ERR(dev->dev); | ||
282 | dev->dev = NULL; | ||
283 | goto out; | ||
284 | } | ||
285 | |||
286 | servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; | ||
287 | |||
288 | for (i=0; i<servo_count; i++) { | ||
289 | rc = device_create_file(dev->dev, &dev_attrs[i]); | ||
290 | if (rc) | ||
291 | goto out2; | ||
269 | } | 292 | } |
270 | 293 | ||
271 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", | 294 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", |
272 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, | 295 | servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); |
273 | dev->type & SERVO_VERSION_30 ? 3 : 2); | ||
274 | 296 | ||
275 | if(!(dev->type & SERVO_VERSION_30)) | 297 | if (!(dev->type & SERVO_VERSION_30)) |
276 | dev_info(&interface->dev, | 298 | dev_info(&interface->dev, |
277 | "WARNING: v2.0 not tested! Please report if it works.\n"); | 299 | "WARNING: v2.0 not tested! Please report if it works.\n"); |
278 | 300 | ||
279 | return 0; | 301 | return 0; |
302 | out2: | ||
303 | while (i-- > 0) | ||
304 | device_remove_file(dev->dev, &dev_attrs[i]); | ||
305 | out: | ||
306 | if (dev) { | ||
307 | if (dev->dev) | ||
308 | device_unregister(dev->dev); | ||
309 | if (dev->dev_no >= 0) | ||
310 | clear_bit(dev->dev_no, &device_no); | ||
311 | |||
312 | kfree(dev); | ||
313 | } | ||
314 | |||
315 | return rc; | ||
280 | } | 316 | } |
281 | 317 | ||
282 | static void | 318 | static void |
283 | servo_disconnect(struct usb_interface *interface) | 319 | servo_disconnect(struct usb_interface *interface) |
284 | { | 320 | { |
285 | struct phidget_servo *dev; | 321 | struct phidget_servo *dev; |
322 | int servo_count, i; | ||
286 | 323 | ||
287 | dev = usb_get_intfdata(interface); | 324 | dev = usb_get_intfdata(interface); |
288 | usb_set_intfdata(interface, NULL); | 325 | usb_set_intfdata(interface, NULL); |
289 | 326 | ||
290 | device_remove_file(&interface->dev, &dev_attr_servo0); | 327 | if (!dev) |
291 | if (dev->type & SERVO_COUNT_QUAD) { | 328 | return; |
292 | device_remove_file(&interface->dev, &dev_attr_servo1); | 329 | |
293 | device_remove_file(&interface->dev, &dev_attr_servo2); | 330 | servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; |
294 | device_remove_file(&interface->dev, &dev_attr_servo3); | 331 | |
295 | } | 332 | for (i=0; i<servo_count; i++) |
333 | device_remove_file(dev->dev, &dev_attrs[i]); | ||
296 | 334 | ||
335 | device_unregister(dev->dev); | ||
297 | usb_put_dev(dev->udev); | 336 | usb_put_dev(dev->udev); |
298 | 337 | ||
299 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", | 338 | dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", |
300 | dev->type & SERVO_COUNT_QUAD ? 4 : 1, | 339 | servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); |
301 | dev->type & SERVO_VERSION_30 ? 3 : 2); | ||
302 | 340 | ||
341 | clear_bit(dev->dev_no, &device_no); | ||
303 | kfree(dev); | 342 | kfree(dev); |
304 | } | 343 | } |
305 | 344 | ||
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index e16582f3733c..a44124c7e851 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
@@ -3179,7 +3179,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
3179 | } | 3179 | } |
3180 | #endif | 3180 | #endif |
3181 | 3181 | ||
3182 | static struct file_operations usb_sisusb_fops = { | 3182 | static const struct file_operations usb_sisusb_fops = { |
3183 | .owner = THIS_MODULE, | 3183 | .owner = THIS_MODULE, |
3184 | .open = sisusb_open, | 3184 | .open = sisusb_open, |
3185 | .release = sisusb_release, | 3185 | .release = sisusb_release, |
diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h new file mode 100644 index 000000000000..551ba8906d62 --- /dev/null +++ b/drivers/usb/misc/usb_u132.h | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * Common Header File for the Elan Digital Systems U132 adapter | ||
3 | * this file should be included by both the "ftdi-u132" and | ||
4 | * the "u132-hcd" modules. | ||
5 | * | ||
6 | * Copyright(C) 2006 Elan Digital Systems Limited | ||
7 | *(http://www.elandigitalsystems.com) | ||
8 | * | ||
9 | * Author and Maintainer - Tony Olech - Elan Digital Systems | ||
10 | *(tony.olech@elandigitalsystems.com) | ||
11 | * | ||
12 | * This program is free software;you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation, version 2. | ||
15 | * | ||
16 | * | ||
17 | * The driver was written by Tony Olech(tony.olech@elandigitalsystems.com) | ||
18 | * based on various USB client drivers in the 2.6.15 linux kernel | ||
19 | * with constant reference to the 3rd Edition of Linux Device Drivers | ||
20 | * published by O'Reilly | ||
21 | * | ||
22 | * The U132 adapter is a USB to CardBus adapter specifically designed | ||
23 | * for PC cards that contain an OHCI host controller. Typical PC cards | ||
24 | * are the Orange Mobile 3G Option GlobeTrotter Fusion card. | ||
25 | * | ||
26 | * The U132 adapter will *NOT *work with PC cards that do not contain | ||
27 | * an OHCI controller. A simple way to test whether a PC card has an | ||
28 | * OHCI controller as an interface is to insert the PC card directly | ||
29 | * into a laptop(or desktop) with a CardBus slot and if "lspci" shows | ||
30 | * a new USB controller and "lsusb -v" shows a new OHCI Host Controller | ||
31 | * then there is a good chance that the U132 adapter will support the | ||
32 | * PC card.(you also need the specific client driver for the PC card) | ||
33 | * | ||
34 | * Please inform the Author and Maintainer about any PC cards that | ||
35 | * contain OHCI Host Controller and work when directly connected to | ||
36 | * an embedded CardBus slot but do not work when they are connected | ||
37 | * via an ELAN U132 adapter. | ||
38 | * | ||
39 | * The driver consists of two modules, the "ftdi-u132" module is | ||
40 | * a USB client driver that interfaces to the FTDI chip within | ||
41 | * the U132 adapter manufactured by Elan Digital Systems, and the | ||
42 | * "u132-hcd" module is a USB host controller driver that talks | ||
43 | * to the OHCI controller within CardBus card that are inserted | ||
44 | * in the U132 adapter. | ||
45 | * | ||
46 | * The "ftdi-u132" module should be loaded automatically by the | ||
47 | * hot plug system when the U132 adapter is plugged in. The module | ||
48 | * initialises the adapter which mostly consists of synchronising | ||
49 | * the FTDI chip, before continuously polling the adapter to detect | ||
50 | * PC card insertions. As soon as a PC card containing a recognised | ||
51 | * OHCI controller is seen the "ftdi-u132" module explicitly requests | ||
52 | * the kernel to load the "u132-hcd" module. | ||
53 | * | ||
54 | * The "ftdi-u132" module provides the interface to the inserted | ||
55 | * PC card and the "u132-hcd" module uses the API to send and recieve | ||
56 | * data. The API features call-backs, so that part of the "u132-hcd" | ||
57 | * module code will run in the context of one of the kernel threads | ||
58 | * of the "ftdi-u132" module. | ||
59 | * | ||
60 | */ | ||
61 | int ftdi_elan_switch_on_diagnostics(int number); | ||
62 | void ftdi_elan_gone_away(struct platform_device *pdev); | ||
63 | void start_usb_lock_device_tracing(void); | ||
64 | struct u132_platform_data { | ||
65 | u16 vendor; | ||
66 | u16 device; | ||
67 | u8 potpg; | ||
68 | void (*port_power) (struct device *dev, int is_on); | ||
69 | void (*reset) (struct device *dev); | ||
70 | }; | ||
71 | int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number, | ||
72 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
73 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
74 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
75 | int halted, int skipped, int actual, int non_null)); | ||
76 | int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number, | ||
77 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
78 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
79 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
80 | int halted, int skipped, int actual, int non_null)); | ||
81 | int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number, | ||
82 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
83 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
84 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
85 | int halted, int skipped, int actual, int non_null)); | ||
86 | int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number, | ||
87 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
88 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
89 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
90 | int halted, int skipped, int actual, int non_null)); | ||
91 | int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number, | ||
92 | void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits, | ||
93 | void (*callback) (void *endp, struct urb *urb, u8 *buf, int len, | ||
94 | int toggle_bits, int error_count, int condition_code, int repeat_number, | ||
95 | int halted, int skipped, int actual, int non_null)); | ||
96 | int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number, | ||
97 | void *endp); | ||
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index e095772dd8e9..dbaca9f1efad 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c | |||
@@ -239,7 +239,7 @@ error: | |||
239 | return retval; | 239 | return retval; |
240 | } | 240 | } |
241 | 241 | ||
242 | static struct file_operations lcd_fops = { | 242 | static const struct file_operations lcd_fops = { |
243 | .owner = THIS_MODULE, | 243 | .owner = THIS_MODULE, |
244 | .read = lcd_read, | 244 | .read = lcd_read, |
245 | .write = lcd_write, | 245 | .write = lcd_write, |
@@ -290,9 +290,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id | |||
290 | endpoint = &iface_desc->endpoint[i].desc; | 290 | endpoint = &iface_desc->endpoint[i].desc; |
291 | 291 | ||
292 | if (!dev->bulk_in_endpointAddr && | 292 | if (!dev->bulk_in_endpointAddr && |
293 | (endpoint->bEndpointAddress & USB_DIR_IN) && | 293 | usb_endpoint_is_bulk_in(endpoint)) { |
294 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
295 | == USB_ENDPOINT_XFER_BULK)) { | ||
296 | /* we found a bulk in endpoint */ | 294 | /* we found a bulk in endpoint */ |
297 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 295 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
298 | dev->bulk_in_size = buffer_size; | 296 | dev->bulk_in_size = buffer_size; |
@@ -305,9 +303,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id | |||
305 | } | 303 | } |
306 | 304 | ||
307 | if (!dev->bulk_out_endpointAddr && | 305 | if (!dev->bulk_out_endpointAddr && |
308 | !(endpoint->bEndpointAddress & USB_DIR_IN) && | 306 | usb_endpoint_is_bulk_out(endpoint)) { |
309 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
310 | == USB_ENDPOINT_XFER_BULK)) { | ||
311 | /* we found a bulk out endpoint */ | 307 | /* we found a bulk out endpoint */ |
312 | dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; | 308 | dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; |
313 | } | 309 | } |
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 0c5ee0ad6bb9..49c5c5c4c431 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c | |||
@@ -108,22 +108,34 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id | |||
108 | dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL); | 108 | dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL); |
109 | if (dev == NULL) { | 109 | if (dev == NULL) { |
110 | dev_err(&interface->dev, "Out of memory\n"); | 110 | dev_err(&interface->dev, "Out of memory\n"); |
111 | goto error; | 111 | goto error_mem; |
112 | } | 112 | } |
113 | 113 | ||
114 | dev->udev = usb_get_dev(udev); | 114 | dev->udev = usb_get_dev(udev); |
115 | 115 | ||
116 | usb_set_intfdata (interface, dev); | 116 | usb_set_intfdata (interface, dev); |
117 | 117 | ||
118 | device_create_file(&interface->dev, &dev_attr_blue); | 118 | retval = device_create_file(&interface->dev, &dev_attr_blue); |
119 | device_create_file(&interface->dev, &dev_attr_red); | 119 | if (retval) |
120 | device_create_file(&interface->dev, &dev_attr_green); | 120 | goto error; |
121 | retval = device_create_file(&interface->dev, &dev_attr_red); | ||
122 | if (retval) | ||
123 | goto error; | ||
124 | retval = device_create_file(&interface->dev, &dev_attr_green); | ||
125 | if (retval) | ||
126 | goto error; | ||
121 | 127 | ||
122 | dev_info(&interface->dev, "USB LED device now attached\n"); | 128 | dev_info(&interface->dev, "USB LED device now attached\n"); |
123 | return 0; | 129 | return 0; |
124 | 130 | ||
125 | error: | 131 | error: |
132 | device_remove_file(&interface->dev, &dev_attr_blue); | ||
133 | device_remove_file(&interface->dev, &dev_attr_red); | ||
134 | device_remove_file(&interface->dev, &dev_attr_green); | ||
135 | usb_set_intfdata (interface, NULL); | ||
136 | usb_put_dev(dev->udev); | ||
126 | kfree(dev); | 137 | kfree(dev); |
138 | error_mem: | ||
127 | return retval; | 139 | return retval; |
128 | } | 140 | } |
129 | 141 | ||
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 275a66f83058..394bbf2f68d4 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c | |||
@@ -265,7 +265,6 @@ static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus) | |||
265 | ubus->mon_bus = NULL; | 265 | ubus->mon_bus = NULL; |
266 | mbus->u_bus = NULL; | 266 | mbus->u_bus = NULL; |
267 | mb(); | 267 | mb(); |
268 | // usb_bus_put(ubus); | ||
269 | } | 268 | } |
270 | 269 | ||
271 | /* | 270 | /* |
@@ -297,12 +296,12 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus) | |||
297 | INIT_LIST_HEAD(&mbus->r_list); | 296 | INIT_LIST_HEAD(&mbus->r_list); |
298 | 297 | ||
299 | /* | 298 | /* |
300 | * This usb_bus_get here is superfluous, because we receive | 299 | * We don't need to take a reference to ubus, because we receive |
301 | * a notification if usb_bus is about to be removed. | 300 | * a notification if the bus is about to be removed. |
302 | */ | 301 | */ |
303 | // usb_bus_get(ubus); | ||
304 | mbus->u_bus = ubus; | 302 | mbus->u_bus = ubus; |
305 | ubus->mon_bus = mbus; | 303 | ubus->mon_bus = mbus; |
304 | mbus->uses_dma = ubus->uses_dma; | ||
306 | 305 | ||
307 | rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); | 306 | rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); |
308 | if (rc <= 0 || rc >= NAMESZ) | 307 | if (rc <= 0 || rc >= NAMESZ) |
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c index 1fe01d994a79..f6d1491256c4 100644 --- a/drivers/usb/mon/mon_stat.c +++ b/drivers/usb/mon/mon_stat.c | |||
@@ -28,7 +28,7 @@ static int mon_stat_open(struct inode *inode, struct file *file) | |||
28 | if ((sp = kmalloc(sizeof(struct snap), GFP_KERNEL)) == NULL) | 28 | if ((sp = kmalloc(sizeof(struct snap), GFP_KERNEL)) == NULL) |
29 | return -ENOMEM; | 29 | return -ENOMEM; |
30 | 30 | ||
31 | mbus = inode->u.generic_ip; | 31 | mbus = inode->i_private; |
32 | 32 | ||
33 | sp->slen = snprintf(sp->str, STAT_BUF_SIZE, | 33 | sp->slen = snprintf(sp->str, STAT_BUF_SIZE, |
34 | "nreaders %d events %u text_lost %u\n", | 34 | "nreaders %d events %u text_lost %u\n", |
@@ -62,7 +62,7 @@ static int mon_stat_release(struct inode *inode, struct file *file) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | struct file_operations mon_fops_stat = { | 65 | const struct file_operations mon_fops_stat = { |
66 | .owner = THIS_MODULE, | 66 | .owner = THIS_MODULE, |
67 | .open = mon_stat_open, | 67 | .open = mon_stat_open, |
68 | .llseek = no_llseek, | 68 | .llseek = no_llseek, |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index f961a770cee2..7a2346c53284 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -75,13 +75,13 @@ static void mon_text_ctor(void *, kmem_cache_t *, unsigned long); | |||
75 | */ | 75 | */ |
76 | 76 | ||
77 | static inline char mon_text_get_setup(struct mon_event_text *ep, | 77 | static inline char mon_text_get_setup(struct mon_event_text *ep, |
78 | struct urb *urb, char ev_type) | 78 | struct urb *urb, char ev_type, struct mon_bus *mbus) |
79 | { | 79 | { |
80 | 80 | ||
81 | if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') | 81 | if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') |
82 | return '-'; | 82 | return '-'; |
83 | 83 | ||
84 | if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP) | 84 | if (mbus->uses_dma && (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) |
85 | return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX); | 85 | return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX); |
86 | if (urb->setup_packet == NULL) | 86 | if (urb->setup_packet == NULL) |
87 | return 'Z'; /* '0' would be not as pretty. */ | 87 | return 'Z'; /* '0' would be not as pretty. */ |
@@ -91,7 +91,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep, | |||
91 | } | 91 | } |
92 | 92 | ||
93 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | 93 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, |
94 | int len, char ev_type) | 94 | int len, char ev_type, struct mon_bus *mbus) |
95 | { | 95 | { |
96 | int pipe = urb->pipe; | 96 | int pipe = urb->pipe; |
97 | 97 | ||
@@ -117,7 +117,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | |||
117 | * contain non-NULL garbage in case the upper level promised to | 117 | * contain non-NULL garbage in case the upper level promised to |
118 | * set DMA for the HCD. | 118 | * set DMA for the HCD. |
119 | */ | 119 | */ |
120 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | 120 | if (mbus->uses_dma && (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) |
121 | return mon_dmapeek(ep->data, urb->transfer_dma, len); | 121 | return mon_dmapeek(ep->data, urb->transfer_dma, len); |
122 | 122 | ||
123 | if (urb->transfer_buffer == NULL) | 123 | if (urb->transfer_buffer == NULL) |
@@ -161,8 +161,9 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, | |||
161 | /* Collecting status makes debugging sense for submits, too */ | 161 | /* Collecting status makes debugging sense for submits, too */ |
162 | ep->status = urb->status; | 162 | ep->status = urb->status; |
163 | 163 | ||
164 | ep->setup_flag = mon_text_get_setup(ep, urb, ev_type); | 164 | ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus); |
165 | ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type); | 165 | ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type, |
166 | rp->r.m_bus); | ||
166 | 167 | ||
167 | rp->nevents++; | 168 | rp->nevents++; |
168 | list_add_tail(&ep->e_link, &rp->e_list); | 169 | list_add_tail(&ep->e_link, &rp->e_list); |
@@ -238,7 +239,7 @@ static int mon_text_open(struct inode *inode, struct file *file) | |||
238 | int rc; | 239 | int rc; |
239 | 240 | ||
240 | mutex_lock(&mon_lock); | 241 | mutex_lock(&mon_lock); |
241 | mbus = inode->u.generic_ip; | 242 | mbus = inode->i_private; |
242 | ubus = mbus->u_bus; | 243 | ubus = mbus->u_bus; |
243 | 244 | ||
244 | rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL); | 245 | rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL); |
@@ -401,7 +402,7 @@ static int mon_text_release(struct inode *inode, struct file *file) | |||
401 | struct mon_event_text *ep; | 402 | struct mon_event_text *ep; |
402 | 403 | ||
403 | mutex_lock(&mon_lock); | 404 | mutex_lock(&mon_lock); |
404 | mbus = inode->u.generic_ip; | 405 | mbus = inode->i_private; |
405 | 406 | ||
406 | if (mbus->nreaders <= 0) { | 407 | if (mbus->nreaders <= 0) { |
407 | printk(KERN_ERR TAG ": consistency error on close\n"); | 408 | printk(KERN_ERR TAG ": consistency error on close\n"); |
@@ -435,7 +436,7 @@ static int mon_text_release(struct inode *inode, struct file *file) | |||
435 | return 0; | 436 | return 0; |
436 | } | 437 | } |
437 | 438 | ||
438 | struct file_operations mon_fops_text = { | 439 | const struct file_operations mon_fops_text = { |
439 | .owner = THIS_MODULE, | 440 | .owner = THIS_MODULE, |
440 | .open = mon_text_open, | 441 | .open = mon_text_open, |
441 | .llseek = no_llseek, | 442 | .llseek = no_llseek, |
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 33678c24ebee..ab9d02d5df77 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h | |||
@@ -20,6 +20,7 @@ struct mon_bus { | |||
20 | struct dentry *dent_s; /* Debugging file */ | 20 | struct dentry *dent_s; /* Debugging file */ |
21 | struct dentry *dent_t; /* Text interface file */ | 21 | struct dentry *dent_t; /* Text interface file */ |
22 | struct usb_bus *u_bus; | 22 | struct usb_bus *u_bus; |
23 | int uses_dma; | ||
23 | 24 | ||
24 | /* Ref */ | 25 | /* Ref */ |
25 | int nreaders; /* Under mon_lock AND mbus->lock */ | 26 | int nreaders; /* Under mon_lock AND mbus->lock */ |
@@ -53,7 +54,7 @@ extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len); | |||
53 | 54 | ||
54 | extern struct mutex mon_lock; | 55 | extern struct mutex mon_lock; |
55 | 56 | ||
56 | extern struct file_operations mon_fops_text; | 57 | extern const struct file_operations mon_fops_text; |
57 | extern struct file_operations mon_fops_stat; | 58 | extern const struct file_operations mon_fops_stat; |
58 | 59 | ||
59 | #endif /* __USB_MON_H */ | 60 | #endif /* __USB_MON_H */ |
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 2e2bbc003e93..9b97aa6384c7 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * ASIX AX8817X based USB 2.0 Ethernet Devices | 2 | * ASIX AX8817X based USB 2.0 Ethernet Devices |
3 | * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> | 3 | * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com> |
4 | * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net> | 4 | * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net> |
5 | * Copyright (C) 2006 James Painter <jamie.painter@iname.com> | ||
5 | * Copyright (c) 2002-2003 TiVo Inc. | 6 | * Copyright (c) 2002-2003 TiVo Inc. |
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -36,6 +37,9 @@ | |||
36 | 37 | ||
37 | #include "usbnet.h" | 38 | #include "usbnet.h" |
38 | 39 | ||
40 | #define DRIVER_VERSION "14-Jun-2006" | ||
41 | static const char driver_name [] = "asix"; | ||
42 | |||
39 | /* ASIX AX8817X based USB 2.0 Ethernet Devices */ | 43 | /* ASIX AX8817X based USB 2.0 Ethernet Devices */ |
40 | 44 | ||
41 | #define AX_CMD_SET_SW_MII 0x06 | 45 | #define AX_CMD_SET_SW_MII 0x06 |
@@ -46,23 +50,25 @@ | |||
46 | #define AX_CMD_WRITE_EEPROM 0x0c | 50 | #define AX_CMD_WRITE_EEPROM 0x0c |
47 | #define AX_CMD_WRITE_ENABLE 0x0d | 51 | #define AX_CMD_WRITE_ENABLE 0x0d |
48 | #define AX_CMD_WRITE_DISABLE 0x0e | 52 | #define AX_CMD_WRITE_DISABLE 0x0e |
53 | #define AX_CMD_READ_RX_CTL 0x0f | ||
49 | #define AX_CMD_WRITE_RX_CTL 0x10 | 54 | #define AX_CMD_WRITE_RX_CTL 0x10 |
50 | #define AX_CMD_READ_IPG012 0x11 | 55 | #define AX_CMD_READ_IPG012 0x11 |
51 | #define AX_CMD_WRITE_IPG0 0x12 | 56 | #define AX_CMD_WRITE_IPG0 0x12 |
52 | #define AX_CMD_WRITE_IPG1 0x13 | 57 | #define AX_CMD_WRITE_IPG1 0x13 |
58 | #define AX_CMD_READ_NODE_ID 0x13 | ||
53 | #define AX_CMD_WRITE_IPG2 0x14 | 59 | #define AX_CMD_WRITE_IPG2 0x14 |
54 | #define AX_CMD_WRITE_MULTI_FILTER 0x16 | 60 | #define AX_CMD_WRITE_MULTI_FILTER 0x16 |
55 | #define AX_CMD_READ_NODE_ID 0x17 | 61 | #define AX88172_CMD_READ_NODE_ID 0x17 |
56 | #define AX_CMD_READ_PHY_ID 0x19 | 62 | #define AX_CMD_READ_PHY_ID 0x19 |
57 | #define AX_CMD_READ_MEDIUM_STATUS 0x1a | 63 | #define AX_CMD_READ_MEDIUM_STATUS 0x1a |
58 | #define AX_CMD_WRITE_MEDIUM_MODE 0x1b | 64 | #define AX_CMD_WRITE_MEDIUM_MODE 0x1b |
59 | #define AX_CMD_READ_MONITOR_MODE 0x1c | 65 | #define AX_CMD_READ_MONITOR_MODE 0x1c |
60 | #define AX_CMD_WRITE_MONITOR_MODE 0x1d | 66 | #define AX_CMD_WRITE_MONITOR_MODE 0x1d |
67 | #define AX_CMD_READ_GPIOS 0x1e | ||
61 | #define AX_CMD_WRITE_GPIOS 0x1f | 68 | #define AX_CMD_WRITE_GPIOS 0x1f |
62 | #define AX_CMD_SW_RESET 0x20 | 69 | #define AX_CMD_SW_RESET 0x20 |
63 | #define AX_CMD_SW_PHY_STATUS 0x21 | 70 | #define AX_CMD_SW_PHY_STATUS 0x21 |
64 | #define AX_CMD_SW_PHY_SELECT 0x22 | 71 | #define AX_CMD_SW_PHY_SELECT 0x22 |
65 | #define AX88772_CMD_READ_NODE_ID 0x13 | ||
66 | 72 | ||
67 | #define AX_MONITOR_MODE 0x01 | 73 | #define AX_MONITOR_MODE 0x01 |
68 | #define AX_MONITOR_LINK 0x02 | 74 | #define AX_MONITOR_LINK 0x02 |
@@ -70,15 +76,15 @@ | |||
70 | #define AX_MONITOR_HSFS 0x10 | 76 | #define AX_MONITOR_HSFS 0x10 |
71 | 77 | ||
72 | /* AX88172 Medium Status Register values */ | 78 | /* AX88172 Medium Status Register values */ |
73 | #define AX_MEDIUM_FULL_DUPLEX 0x02 | 79 | #define AX88172_MEDIUM_FD 0x02 |
74 | #define AX_MEDIUM_TX_ABORT_ALLOW 0x04 | 80 | #define AX88172_MEDIUM_TX 0x04 |
75 | #define AX_MEDIUM_FLOW_CONTROL_EN 0x10 | 81 | #define AX88172_MEDIUM_FC 0x10 |
82 | #define AX88172_MEDIUM_DEFAULT \ | ||
83 | ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC ) | ||
76 | 84 | ||
77 | #define AX_MCAST_FILTER_SIZE 8 | 85 | #define AX_MCAST_FILTER_SIZE 8 |
78 | #define AX_MAX_MCAST 64 | 86 | #define AX_MAX_MCAST 64 |
79 | 87 | ||
80 | #define AX_EEPROM_LEN 0x40 | ||
81 | |||
82 | #define AX_SWRESET_CLEAR 0x00 | 88 | #define AX_SWRESET_CLEAR 0x00 |
83 | #define AX_SWRESET_RR 0x01 | 89 | #define AX_SWRESET_RR 0x01 |
84 | #define AX_SWRESET_RT 0x02 | 90 | #define AX_SWRESET_RT 0x02 |
@@ -92,23 +98,78 @@ | |||
92 | #define AX88772_IPG1_DEFAULT 0x0c | 98 | #define AX88772_IPG1_DEFAULT 0x0c |
93 | #define AX88772_IPG2_DEFAULT 0x12 | 99 | #define AX88772_IPG2_DEFAULT 0x12 |
94 | 100 | ||
95 | #define AX88772_MEDIUM_FULL_DUPLEX 0x0002 | 101 | /* AX88772 & AX88178 Medium Mode Register */ |
96 | #define AX88772_MEDIUM_RESERVED 0x0004 | 102 | #define AX_MEDIUM_PF 0x0080 |
97 | #define AX88772_MEDIUM_RX_FC_ENABLE 0x0010 | 103 | #define AX_MEDIUM_JFE 0x0040 |
98 | #define AX88772_MEDIUM_TX_FC_ENABLE 0x0020 | 104 | #define AX_MEDIUM_TFC 0x0020 |
99 | #define AX88772_MEDIUM_PAUSE_FORMAT 0x0080 | 105 | #define AX_MEDIUM_RFC 0x0010 |
100 | #define AX88772_MEDIUM_RX_ENABLE 0x0100 | 106 | #define AX_MEDIUM_ENCK 0x0008 |
101 | #define AX88772_MEDIUM_100MB 0x0200 | 107 | #define AX_MEDIUM_AC 0x0004 |
102 | #define AX88772_MEDIUM_DEFAULT \ | 108 | #define AX_MEDIUM_FD 0x0002 |
103 | (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \ | 109 | #define AX_MEDIUM_GM 0x0001 |
104 | AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \ | 110 | #define AX_MEDIUM_SM 0x1000 |
105 | AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE ) | 111 | #define AX_MEDIUM_SBP 0x0800 |
112 | #define AX_MEDIUM_PS 0x0200 | ||
113 | #define AX_MEDIUM_RE 0x0100 | ||
114 | |||
115 | #define AX88178_MEDIUM_DEFAULT \ | ||
116 | (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ | ||
117 | AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ | ||
118 | AX_MEDIUM_RE ) | ||
106 | 119 | ||
107 | #define AX_EEPROM_MAGIC 0xdeadbeef | 120 | #define AX88772_MEDIUM_DEFAULT \ |
121 | (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ | ||
122 | AX_MEDIUM_TFC | AX_MEDIUM_PS | \ | ||
123 | AX_MEDIUM_AC | AX_MEDIUM_RE ) | ||
124 | |||
125 | /* AX88772 & AX88178 RX_CTL values */ | ||
126 | #define AX_RX_CTL_SO 0x0080 | ||
127 | #define AX_RX_CTL_AP 0x0020 | ||
128 | #define AX_RX_CTL_AM 0x0010 | ||
129 | #define AX_RX_CTL_AB 0x0008 | ||
130 | #define AX_RX_CTL_SEP 0x0004 | ||
131 | #define AX_RX_CTL_AMALL 0x0002 | ||
132 | #define AX_RX_CTL_PRO 0x0001 | ||
133 | #define AX_RX_CTL_MFB_2048 0x0000 | ||
134 | #define AX_RX_CTL_MFB_4096 0x0100 | ||
135 | #define AX_RX_CTL_MFB_8192 0x0200 | ||
136 | #define AX_RX_CTL_MFB_16384 0x0300 | ||
137 | |||
138 | #define AX_DEFAULT_RX_CTL \ | ||
139 | (AX_RX_CTL_SO | AX_RX_CTL_AB ) | ||
140 | |||
141 | /* GPIO 0 .. 2 toggles */ | ||
142 | #define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ | ||
143 | #define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */ | ||
144 | #define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */ | ||
145 | #define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */ | ||
146 | #define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ | ||
147 | #define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ | ||
148 | #define AX_GPIO_RESERVED 0x40 /* Reserved */ | ||
149 | #define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ | ||
150 | |||
151 | #define AX_EEPROM_MAGIC 0xdeadbeef | ||
152 | #define AX88172_EEPROM_LEN 0x40 | ||
153 | #define AX88772_EEPROM_LEN 0xff | ||
154 | |||
155 | #define PHY_MODE_MARVELL 0x0000 | ||
156 | #define MII_MARVELL_LED_CTRL 0x0018 | ||
157 | #define MII_MARVELL_STATUS 0x001b | ||
158 | #define MII_MARVELL_CTRL 0x0014 | ||
159 | |||
160 | #define MARVELL_LED_MANUAL 0x0019 | ||
161 | |||
162 | #define MARVELL_STATUS_HWCFG 0x0004 | ||
163 | |||
164 | #define MARVELL_CTRL_TXDELAY 0x0002 | ||
165 | #define MARVELL_CTRL_RXDELAY 0x0080 | ||
108 | 166 | ||
109 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ | 167 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ |
110 | struct asix_data { | 168 | struct asix_data { |
111 | u8 multi_filter[AX_MCAST_FILTER_SIZE]; | 169 | u8 multi_filter[AX_MCAST_FILTER_SIZE]; |
170 | u8 phymode; | ||
171 | u8 ledmode; | ||
172 | u8 eeprom_len; | ||
112 | }; | 173 | }; |
113 | 174 | ||
114 | struct ax88172_int_data { | 175 | struct ax88172_int_data { |
@@ -122,6 +183,8 @@ struct ax88172_int_data { | |||
122 | static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | 183 | static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, |
123 | u16 size, void *data) | 184 | u16 size, void *data) |
124 | { | 185 | { |
186 | devdbg(dev,"asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", | ||
187 | cmd, value, index, size); | ||
125 | return usb_control_msg( | 188 | return usb_control_msg( |
126 | dev->udev, | 189 | dev->udev, |
127 | usb_rcvctrlpipe(dev->udev, 0), | 190 | usb_rcvctrlpipe(dev->udev, 0), |
@@ -137,6 +200,8 @@ static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | |||
137 | static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | 200 | static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, |
138 | u16 size, void *data) | 201 | u16 size, void *data) |
139 | { | 202 | { |
203 | devdbg(dev,"asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", | ||
204 | cmd, value, index, size); | ||
140 | return usb_control_msg( | 205 | return usb_control_msg( |
141 | dev->udev, | 206 | dev->udev, |
142 | usb_sndctrlpipe(dev->udev, 0), | 207 | usb_sndctrlpipe(dev->udev, 0), |
@@ -161,12 +226,167 @@ static void asix_async_cmd_callback(struct urb *urb, struct pt_regs *regs) | |||
161 | usb_free_urb(urb); | 226 | usb_free_urb(urb); |
162 | } | 227 | } |
163 | 228 | ||
229 | static void | ||
230 | asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
231 | u16 size, void *data) | ||
232 | { | ||
233 | struct usb_ctrlrequest *req; | ||
234 | int status; | ||
235 | struct urb *urb; | ||
236 | |||
237 | devdbg(dev,"asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d", | ||
238 | cmd, value, index, size); | ||
239 | if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) { | ||
240 | deverr(dev, "Error allocating URB in write_cmd_async!"); | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) { | ||
245 | deverr(dev, "Failed to allocate memory for control request"); | ||
246 | usb_free_urb(urb); | ||
247 | return; | ||
248 | } | ||
249 | |||
250 | req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
251 | req->bRequest = cmd; | ||
252 | req->wValue = value; | ||
253 | req->wIndex = index; | ||
254 | req->wLength = size; | ||
255 | |||
256 | usb_fill_control_urb(urb, dev->udev, | ||
257 | usb_sndctrlpipe(dev->udev, 0), | ||
258 | (void *)req, data, size, | ||
259 | asix_async_cmd_callback, req); | ||
260 | |||
261 | if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { | ||
262 | deverr(dev, "Error submitting the control message: status=%d", | ||
263 | status); | ||
264 | kfree(req); | ||
265 | usb_free_urb(urb); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
270 | { | ||
271 | u8 *head; | ||
272 | u32 header; | ||
273 | char *packet; | ||
274 | struct sk_buff *ax_skb; | ||
275 | u16 size; | ||
276 | |||
277 | head = (u8 *) skb->data; | ||
278 | memcpy(&header, head, sizeof(header)); | ||
279 | le32_to_cpus(&header); | ||
280 | packet = head + sizeof(header); | ||
281 | |||
282 | skb_pull(skb, 4); | ||
283 | |||
284 | while (skb->len > 0) { | ||
285 | if ((short)(header & 0x0000ffff) != | ||
286 | ~((short)((header & 0xffff0000) >> 16))) { | ||
287 | deverr(dev,"asix_rx_fixup() Bad Header Length"); | ||
288 | } | ||
289 | /* get the packet length */ | ||
290 | size = (u16) (header & 0x0000ffff); | ||
291 | |||
292 | if ((skb->len) - ((size + 1) & 0xfffe) == 0) | ||
293 | return 2; | ||
294 | if (size > ETH_FRAME_LEN) { | ||
295 | deverr(dev,"asix_rx_fixup() Bad RX Length %d", size); | ||
296 | return 0; | ||
297 | } | ||
298 | ax_skb = skb_clone(skb, GFP_ATOMIC); | ||
299 | if (ax_skb) { | ||
300 | ax_skb->len = size; | ||
301 | ax_skb->data = packet; | ||
302 | ax_skb->tail = packet + size; | ||
303 | usbnet_skb_return(dev, ax_skb); | ||
304 | } else { | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | skb_pull(skb, (size + 1) & 0xfffe); | ||
309 | |||
310 | if (skb->len == 0) | ||
311 | break; | ||
312 | |||
313 | head = (u8 *) skb->data; | ||
314 | memcpy(&header, head, sizeof(header)); | ||
315 | le32_to_cpus(&header); | ||
316 | packet = head + sizeof(header); | ||
317 | skb_pull(skb, 4); | ||
318 | } | ||
319 | |||
320 | if (skb->len < 0) { | ||
321 | deverr(dev,"asix_rx_fixup() Bad SKB Length %d", skb->len); | ||
322 | return 0; | ||
323 | } | ||
324 | return 1; | ||
325 | } | ||
326 | |||
327 | static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | ||
328 | gfp_t flags) | ||
329 | { | ||
330 | int padlen; | ||
331 | int headroom = skb_headroom(skb); | ||
332 | int tailroom = skb_tailroom(skb); | ||
333 | u32 packet_len; | ||
334 | u32 padbytes = 0xffff0000; | ||
335 | |||
336 | padlen = ((skb->len + 4) % 512) ? 0 : 4; | ||
337 | |||
338 | if ((!skb_cloned(skb)) | ||
339 | && ((headroom + tailroom) >= (4 + padlen))) { | ||
340 | if ((headroom < 4) || (tailroom < padlen)) { | ||
341 | skb->data = memmove(skb->head + 4, skb->data, skb->len); | ||
342 | skb->tail = skb->data + skb->len; | ||
343 | } | ||
344 | } else { | ||
345 | struct sk_buff *skb2; | ||
346 | skb2 = skb_copy_expand(skb, 4, padlen, flags); | ||
347 | dev_kfree_skb_any(skb); | ||
348 | skb = skb2; | ||
349 | if (!skb) | ||
350 | return NULL; | ||
351 | } | ||
352 | |||
353 | skb_push(skb, 4); | ||
354 | packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); | ||
355 | memcpy(skb->data, &packet_len, sizeof(packet_len)); | ||
356 | |||
357 | if ((skb->len % 512) == 0) { | ||
358 | memcpy( skb->tail, &padbytes, sizeof(padbytes)); | ||
359 | skb_put(skb, sizeof(padbytes)); | ||
360 | } | ||
361 | return skb; | ||
362 | } | ||
363 | |||
364 | static void asix_status(struct usbnet *dev, struct urb *urb) | ||
365 | { | ||
366 | struct ax88172_int_data *event; | ||
367 | int link; | ||
368 | |||
369 | if (urb->actual_length < 8) | ||
370 | return; | ||
371 | |||
372 | event = urb->transfer_buffer; | ||
373 | link = event->link & 0x01; | ||
374 | if (netif_carrier_ok(dev->net) != link) { | ||
375 | if (link) { | ||
376 | netif_carrier_on(dev->net); | ||
377 | usbnet_defer_kevent (dev, EVENT_LINK_RESET ); | ||
378 | } else | ||
379 | netif_carrier_off(dev->net); | ||
380 | devdbg(dev, "Link Status is: %d", link); | ||
381 | } | ||
382 | } | ||
383 | |||
164 | static inline int asix_set_sw_mii(struct usbnet *dev) | 384 | static inline int asix_set_sw_mii(struct usbnet *dev) |
165 | { | 385 | { |
166 | int ret; | 386 | int ret; |
167 | ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); | 387 | ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); |
168 | if (ret < 0) | 388 | if (ret < 0) |
169 | devdbg(dev, "Failed to enable software MII access"); | 389 | deverr(dev, "Failed to enable software MII access"); |
170 | return ret; | 390 | return ret; |
171 | } | 391 | } |
172 | 392 | ||
@@ -175,24 +395,27 @@ static inline int asix_set_hw_mii(struct usbnet *dev) | |||
175 | int ret; | 395 | int ret; |
176 | ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); | 396 | ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); |
177 | if (ret < 0) | 397 | if (ret < 0) |
178 | devdbg(dev, "Failed to enable hardware MII access"); | 398 | deverr(dev, "Failed to enable hardware MII access"); |
179 | return ret; | 399 | return ret; |
180 | } | 400 | } |
181 | 401 | ||
182 | static inline int asix_get_phyid(struct usbnet *dev) | 402 | static inline int asix_get_phy_addr(struct usbnet *dev) |
183 | { | 403 | { |
184 | int ret = 0; | 404 | int ret = 0; |
185 | void *buf; | 405 | void *buf; |
186 | 406 | ||
407 | devdbg(dev, "asix_get_phy_addr()"); | ||
408 | |||
187 | buf = kmalloc(2, GFP_KERNEL); | 409 | buf = kmalloc(2, GFP_KERNEL); |
188 | if (!buf) | 410 | if (!buf) |
189 | goto out1; | 411 | goto out1; |
190 | 412 | ||
191 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, | 413 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, |
192 | 0, 0, 2, buf)) < 2) { | 414 | 0, 0, 2, buf)) < 2) { |
193 | devdbg(dev, "Error reading PHYID register: %02x", ret); | 415 | deverr(dev, "Error reading PHYID register: %02x", ret); |
194 | goto out2; | 416 | goto out2; |
195 | } | 417 | } |
418 | devdbg(dev, "asix_get_phy_addr() returning 0x%04x", *((u16 *)buf)); | ||
196 | ret = *((u8 *)buf + 1); | 419 | ret = *((u8 *)buf + 1); |
197 | out2: | 420 | out2: |
198 | kfree(buf); | 421 | kfree(buf); |
@@ -206,8 +429,29 @@ static int asix_sw_reset(struct usbnet *dev, u8 flags) | |||
206 | 429 | ||
207 | ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); | 430 | ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); |
208 | if (ret < 0) | 431 | if (ret < 0) |
209 | devdbg(dev,"Failed to send software reset: %02x", ret); | 432 | deverr(dev,"Failed to send software reset: %02x", ret); |
433 | |||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | static u16 asix_read_rx_ctl(struct usbnet *dev) | ||
438 | { | ||
439 | u16 ret = 0; | ||
440 | void *buf; | ||
441 | |||
442 | buf = kmalloc(2, GFP_KERNEL); | ||
443 | if (!buf) | ||
444 | goto out1; | ||
210 | 445 | ||
446 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, | ||
447 | 0, 0, 2, buf)) < 2) { | ||
448 | deverr(dev, "Error reading RX_CTL register: %02x", ret); | ||
449 | goto out2; | ||
450 | } | ||
451 | ret = le16_to_cpu(*((u16 *)buf)); | ||
452 | out2: | ||
453 | kfree(buf); | ||
454 | out1: | ||
211 | return ret; | 455 | return ret; |
212 | } | 456 | } |
213 | 457 | ||
@@ -215,82 +459,79 @@ static int asix_write_rx_ctl(struct usbnet *dev, u16 mode) | |||
215 | { | 459 | { |
216 | int ret; | 460 | int ret; |
217 | 461 | ||
462 | devdbg(dev,"asix_write_rx_ctl() - mode = 0x%04x", mode); | ||
218 | ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); | 463 | ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); |
219 | if (ret < 0) | 464 | if (ret < 0) |
220 | devdbg(dev, "Failed to write RX_CTL mode: %02x", ret); | 465 | deverr(dev, "Failed to write RX_CTL mode to 0x%04x: %02x", |
466 | mode, ret); | ||
221 | 467 | ||
222 | return ret; | 468 | return ret; |
223 | } | 469 | } |
224 | 470 | ||
225 | static void asix_status(struct usbnet *dev, struct urb *urb) | 471 | static u16 asix_read_medium_status(struct usbnet *dev) |
226 | { | 472 | { |
227 | struct ax88172_int_data *event; | 473 | u16 ret = 0; |
228 | int link; | 474 | void *buf; |
229 | 475 | ||
230 | if (urb->actual_length < 8) | 476 | buf = kmalloc(2, GFP_KERNEL); |
231 | return; | 477 | if (!buf) |
478 | goto out1; | ||
232 | 479 | ||
233 | event = urb->transfer_buffer; | 480 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, |
234 | link = event->link & 0x01; | 481 | 0, 0, 2, buf)) < 2) { |
235 | if (netif_carrier_ok(dev->net) != link) { | 482 | deverr(dev, "Error reading Medium Status register: %02x", ret); |
236 | if (link) { | 483 | goto out2; |
237 | netif_carrier_on(dev->net); | ||
238 | usbnet_defer_kevent (dev, EVENT_LINK_RESET ); | ||
239 | } else | ||
240 | netif_carrier_off(dev->net); | ||
241 | devdbg(dev, "Link Status is: %d", link); | ||
242 | } | 484 | } |
485 | ret = le16_to_cpu(*((u16 *)buf)); | ||
486 | out2: | ||
487 | kfree(buf); | ||
488 | out1: | ||
489 | return ret; | ||
243 | } | 490 | } |
244 | 491 | ||
245 | static void | 492 | static int asix_write_medium_mode(struct usbnet *dev, u16 mode) |
246 | asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
247 | u16 size, void *data) | ||
248 | { | 493 | { |
249 | struct usb_ctrlrequest *req; | 494 | int ret; |
250 | int status; | ||
251 | struct urb *urb; | ||
252 | 495 | ||
253 | if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) { | 496 | devdbg(dev,"asix_write_medium_mode() - mode = 0x%04x", mode); |
254 | devdbg(dev, "Error allocating URB in write_cmd_async!"); | 497 | ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); |
255 | return; | 498 | if (ret < 0) |
256 | } | 499 | deverr(dev, "Failed to write Medium Mode mode to 0x%04x: %02x", |
500 | mode, ret); | ||
257 | 501 | ||
258 | if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) { | 502 | return ret; |
259 | deverr(dev, "Failed to allocate memory for control request"); | 503 | } |
260 | usb_free_urb(urb); | ||
261 | return; | ||
262 | } | ||
263 | 504 | ||
264 | req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | 505 | static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) |
265 | req->bRequest = cmd; | 506 | { |
266 | req->wValue = cpu_to_le16(value); | 507 | int ret; |
267 | req->wIndex = cpu_to_le16(index); | ||
268 | req->wLength = cpu_to_le16(size); | ||
269 | 508 | ||
270 | usb_fill_control_urb(urb, dev->udev, | 509 | devdbg(dev,"asix_write_gpio() - value = 0x%04x", value); |
271 | usb_sndctrlpipe(dev->udev, 0), | 510 | ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL); |
272 | (void *)req, data, size, | 511 | if (ret < 0) |
273 | asix_async_cmd_callback, req); | 512 | deverr(dev, "Failed to write GPIO value 0x%04x: %02x", |
513 | value, ret); | ||
274 | 514 | ||
275 | if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { | 515 | if (sleep) |
276 | deverr(dev, "Error submitting the control message: status=%d", | 516 | msleep(sleep); |
277 | status); | 517 | |
278 | kfree(req); | 518 | return ret; |
279 | usb_free_urb(urb); | ||
280 | } | ||
281 | } | 519 | } |
282 | 520 | ||
521 | /* | ||
522 | * AX88772 & AX88178 have a 16-bit RX_CTL value | ||
523 | */ | ||
283 | static void asix_set_multicast(struct net_device *net) | 524 | static void asix_set_multicast(struct net_device *net) |
284 | { | 525 | { |
285 | struct usbnet *dev = netdev_priv(net); | 526 | struct usbnet *dev = netdev_priv(net); |
286 | struct asix_data *data = (struct asix_data *)&dev->data; | 527 | struct asix_data *data = (struct asix_data *)&dev->data; |
287 | u8 rx_ctl = 0x8c; | 528 | u16 rx_ctl = AX_DEFAULT_RX_CTL; |
288 | 529 | ||
289 | if (net->flags & IFF_PROMISC) { | 530 | if (net->flags & IFF_PROMISC) { |
290 | rx_ctl |= 0x01; | 531 | rx_ctl |= AX_RX_CTL_PRO; |
291 | } else if (net->flags & IFF_ALLMULTI | 532 | } else if (net->flags & IFF_ALLMULTI |
292 | || net->mc_count > AX_MAX_MCAST) { | 533 | || net->mc_count > AX_MAX_MCAST) { |
293 | rx_ctl |= 0x02; | 534 | rx_ctl |= AX_RX_CTL_AMALL; |
294 | } else if (net->mc_count == 0) { | 535 | } else if (net->mc_count == 0) { |
295 | /* just broadcast and directed */ | 536 | /* just broadcast and directed */ |
296 | } else { | 537 | } else { |
@@ -317,7 +558,7 @@ static void asix_set_multicast(struct net_device *net) | |||
317 | asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, | 558 | asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, |
318 | AX_MCAST_FILTER_SIZE, data->multi_filter); | 559 | AX_MCAST_FILTER_SIZE, data->multi_filter); |
319 | 560 | ||
320 | rx_ctl |= 0x10; | 561 | rx_ctl |= AX_RX_CTL_AM; |
321 | } | 562 | } |
322 | 563 | ||
323 | asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); | 564 | asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); |
@@ -333,50 +574,43 @@ static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) | |||
333 | (__u16)loc, 2, (u16 *)&res); | 574 | (__u16)loc, 2, (u16 *)&res); |
334 | asix_set_hw_mii(dev); | 575 | asix_set_hw_mii(dev); |
335 | 576 | ||
336 | return res & 0xffff; | 577 | devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res & 0xffff)); |
337 | } | ||
338 | 578 | ||
339 | /* same as above, but converts resulting value to cpu byte order */ | 579 | return le16_to_cpu(res & 0xffff); |
340 | static int asix_mdio_read_le(struct net_device *netdev, int phy_id, int loc) | ||
341 | { | ||
342 | return le16_to_cpu(asix_mdio_read(netdev,phy_id, loc)); | ||
343 | } | 580 | } |
344 | 581 | ||
345 | static void | 582 | static void |
346 | asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) | 583 | asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) |
347 | { | 584 | { |
348 | struct usbnet *dev = netdev_priv(netdev); | 585 | struct usbnet *dev = netdev_priv(netdev); |
349 | u16 res = val; | 586 | u16 res = cpu_to_le16(val); |
350 | 587 | ||
588 | devdbg(dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val); | ||
351 | asix_set_sw_mii(dev); | 589 | asix_set_sw_mii(dev); |
352 | asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, | 590 | asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, |
353 | (__u16)loc, 2, (u16 *)&res); | 591 | (__u16)loc, 2, (u16 *)&res); |
354 | asix_set_hw_mii(dev); | 592 | asix_set_hw_mii(dev); |
355 | } | 593 | } |
356 | 594 | ||
357 | /* same as above, but converts new value to le16 byte order before writing */ | 595 | /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ |
358 | static void | 596 | static u32 asix_get_phyid(struct usbnet *dev) |
359 | asix_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val) | ||
360 | { | 597 | { |
361 | asix_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) ); | 598 | int phy_reg; |
362 | } | 599 | u32 phy_id; |
363 | 600 | ||
364 | static int ax88172_link_reset(struct usbnet *dev) | 601 | phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); |
365 | { | 602 | if (phy_reg < 0) |
366 | u16 lpa; | 603 | return 0; |
367 | u16 adv; | ||
368 | u16 res; | ||
369 | u8 mode; | ||
370 | 604 | ||
371 | mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN; | 605 | phy_id = (phy_reg & 0xffff) << 16; |
372 | lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA); | ||
373 | adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE); | ||
374 | res = mii_nway_result(lpa|adv); | ||
375 | if (res & LPA_DUPLEX) | ||
376 | mode |= AX_MEDIUM_FULL_DUPLEX; | ||
377 | asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); | ||
378 | 606 | ||
379 | return 0; | 607 | phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2); |
608 | if (phy_reg < 0) | ||
609 | return 0; | ||
610 | |||
611 | phy_id |= (phy_reg & 0xffff); | ||
612 | |||
613 | return phy_id; | ||
380 | } | 614 | } |
381 | 615 | ||
382 | static void | 616 | static void |
@@ -423,7 +657,10 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | |||
423 | 657 | ||
424 | static int asix_get_eeprom_len(struct net_device *net) | 658 | static int asix_get_eeprom_len(struct net_device *net) |
425 | { | 659 | { |
426 | return AX_EEPROM_LEN; | 660 | struct usbnet *dev = netdev_priv(net); |
661 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
662 | |||
663 | return data->eeprom_len; | ||
427 | } | 664 | } |
428 | 665 | ||
429 | static int asix_get_eeprom(struct net_device *net, | 666 | static int asix_get_eeprom(struct net_device *net, |
@@ -453,9 +690,14 @@ static int asix_get_eeprom(struct net_device *net, | |||
453 | static void asix_get_drvinfo (struct net_device *net, | 690 | static void asix_get_drvinfo (struct net_device *net, |
454 | struct ethtool_drvinfo *info) | 691 | struct ethtool_drvinfo *info) |
455 | { | 692 | { |
693 | struct usbnet *dev = netdev_priv(net); | ||
694 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
695 | |||
456 | /* Inherit standard device info */ | 696 | /* Inherit standard device info */ |
457 | usbnet_get_drvinfo(net, info); | 697 | usbnet_get_drvinfo(net, info); |
458 | info->eedump_len = 0x3e; | 698 | strncpy (info->driver, driver_name, sizeof info->driver); |
699 | strncpy (info->version, DRIVER_VERSION, sizeof info->version); | ||
700 | info->eedump_len = data->eeprom_len; | ||
459 | } | 701 | } |
460 | 702 | ||
461 | static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd) | 703 | static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd) |
@@ -468,8 +710,34 @@ static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd) | |||
468 | static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd) | 710 | static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd) |
469 | { | 711 | { |
470 | struct usbnet *dev = netdev_priv(net); | 712 | struct usbnet *dev = netdev_priv(net); |
713 | int res = mii_ethtool_sset(&dev->mii,cmd); | ||
714 | |||
715 | /* link speed/duplex might have changed */ | ||
716 | if (dev->driver_info->link_reset) | ||
717 | dev->driver_info->link_reset(dev); | ||
718 | |||
719 | return res; | ||
720 | } | ||
721 | |||
722 | static int asix_nway_reset(struct net_device *net) | ||
723 | { | ||
724 | struct usbnet *dev = netdev_priv(net); | ||
725 | |||
726 | return mii_nway_restart(&dev->mii); | ||
727 | } | ||
728 | |||
729 | static u32 asix_get_link(struct net_device *net) | ||
730 | { | ||
731 | struct usbnet *dev = netdev_priv(net); | ||
471 | 732 | ||
472 | return mii_ethtool_sset(&dev->mii,cmd); | 733 | return mii_link_ok(&dev->mii); |
734 | } | ||
735 | |||
736 | static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) | ||
737 | { | ||
738 | struct usbnet *dev = netdev_priv(net); | ||
739 | |||
740 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
473 | } | 741 | } |
474 | 742 | ||
475 | /* We need to override some ethtool_ops so we require our | 743 | /* We need to override some ethtool_ops so we require our |
@@ -477,7 +745,8 @@ static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd) | |||
477 | devices that may be connected at the same time. */ | 745 | devices that may be connected at the same time. */ |
478 | static struct ethtool_ops ax88172_ethtool_ops = { | 746 | static struct ethtool_ops ax88172_ethtool_ops = { |
479 | .get_drvinfo = asix_get_drvinfo, | 747 | .get_drvinfo = asix_get_drvinfo, |
480 | .get_link = ethtool_op_get_link, | 748 | .get_link = asix_get_link, |
749 | .nway_reset = asix_nway_reset, | ||
481 | .get_msglevel = usbnet_get_msglevel, | 750 | .get_msglevel = usbnet_get_msglevel, |
482 | .set_msglevel = usbnet_set_msglevel, | 751 | .set_msglevel = usbnet_set_msglevel, |
483 | .get_wol = asix_get_wol, | 752 | .get_wol = asix_get_wol, |
@@ -488,11 +757,66 @@ static struct ethtool_ops ax88172_ethtool_ops = { | |||
488 | .set_settings = asix_set_settings, | 757 | .set_settings = asix_set_settings, |
489 | }; | 758 | }; |
490 | 759 | ||
491 | static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) | 760 | static void ax88172_set_multicast(struct net_device *net) |
492 | { | 761 | { |
493 | struct usbnet *dev = netdev_priv(net); | 762 | struct usbnet *dev = netdev_priv(net); |
763 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
764 | u8 rx_ctl = 0x8c; | ||
494 | 765 | ||
495 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | 766 | if (net->flags & IFF_PROMISC) { |
767 | rx_ctl |= 0x01; | ||
768 | } else if (net->flags & IFF_ALLMULTI | ||
769 | || net->mc_count > AX_MAX_MCAST) { | ||
770 | rx_ctl |= 0x02; | ||
771 | } else if (net->mc_count == 0) { | ||
772 | /* just broadcast and directed */ | ||
773 | } else { | ||
774 | /* We use the 20 byte dev->data | ||
775 | * for our 8 byte filter buffer | ||
776 | * to avoid allocating memory that | ||
777 | * is tricky to free later */ | ||
778 | struct dev_mc_list *mc_list = net->mc_list; | ||
779 | u32 crc_bits; | ||
780 | int i; | ||
781 | |||
782 | memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); | ||
783 | |||
784 | /* Build the multicast hash filter. */ | ||
785 | for (i = 0; i < net->mc_count; i++) { | ||
786 | crc_bits = | ||
787 | ether_crc(ETH_ALEN, | ||
788 | mc_list->dmi_addr) >> 26; | ||
789 | data->multi_filter[crc_bits >> 3] |= | ||
790 | 1 << (crc_bits & 7); | ||
791 | mc_list = mc_list->next; | ||
792 | } | ||
793 | |||
794 | asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, | ||
795 | AX_MCAST_FILTER_SIZE, data->multi_filter); | ||
796 | |||
797 | rx_ctl |= 0x10; | ||
798 | } | ||
799 | |||
800 | asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); | ||
801 | } | ||
802 | |||
803 | static int ax88172_link_reset(struct usbnet *dev) | ||
804 | { | ||
805 | u8 mode; | ||
806 | struct ethtool_cmd ecmd; | ||
807 | |||
808 | mii_check_media(&dev->mii, 1, 1); | ||
809 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
810 | mode = AX88172_MEDIUM_DEFAULT; | ||
811 | |||
812 | if (ecmd.duplex != DUPLEX_FULL) | ||
813 | mode |= ~AX88172_MEDIUM_FD; | ||
814 | |||
815 | devdbg(dev, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode); | ||
816 | |||
817 | asix_write_medium_mode(dev, mode); | ||
818 | |||
819 | return 0; | ||
496 | } | 820 | } |
497 | 821 | ||
498 | static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) | 822 | static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) |
@@ -501,6 +825,9 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) | |||
501 | void *buf; | 825 | void *buf; |
502 | int i; | 826 | int i; |
503 | unsigned long gpio_bits = dev->driver_info->data; | 827 | unsigned long gpio_bits = dev->driver_info->data; |
828 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
829 | |||
830 | data->eeprom_len = AX88172_EEPROM_LEN; | ||
504 | 831 | ||
505 | usbnet_get_endpoints(dev,intf); | 832 | usbnet_get_endpoints(dev,intf); |
506 | 833 | ||
@@ -519,12 +846,12 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) | |||
519 | msleep(5); | 846 | msleep(5); |
520 | } | 847 | } |
521 | 848 | ||
522 | if ((ret = asix_write_rx_ctl(dev,0x80)) < 0) | 849 | if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0) |
523 | goto out2; | 850 | goto out2; |
524 | 851 | ||
525 | /* Get the MAC address */ | 852 | /* Get the MAC address */ |
526 | memset(buf, 0, ETH_ALEN); | 853 | memset(buf, 0, ETH_ALEN); |
527 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, | 854 | if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID, |
528 | 0, 0, 6, buf)) < 0) { | 855 | 0, 0, 6, buf)) < 0) { |
529 | dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); | 856 | dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); |
530 | goto out2; | 857 | goto out2; |
@@ -537,14 +864,14 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) | |||
537 | dev->mii.mdio_write = asix_mdio_write; | 864 | dev->mii.mdio_write = asix_mdio_write; |
538 | dev->mii.phy_id_mask = 0x3f; | 865 | dev->mii.phy_id_mask = 0x3f; |
539 | dev->mii.reg_num_mask = 0x1f; | 866 | dev->mii.reg_num_mask = 0x1f; |
540 | dev->mii.phy_id = asix_get_phyid(dev); | 867 | dev->mii.phy_id = asix_get_phy_addr(dev); |
541 | dev->net->do_ioctl = asix_ioctl; | 868 | dev->net->do_ioctl = asix_ioctl; |
542 | 869 | ||
543 | dev->net->set_multicast_list = asix_set_multicast; | 870 | dev->net->set_multicast_list = ax88172_set_multicast; |
544 | dev->net->ethtool_ops = &ax88172_ethtool_ops; | 871 | dev->net->ethtool_ops = &ax88172_ethtool_ops; |
545 | 872 | ||
546 | asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | 873 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); |
547 | asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE, | 874 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, |
548 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); | 875 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); |
549 | mii_nway_restart(&dev->mii); | 876 | mii_nway_restart(&dev->mii); |
550 | 877 | ||
@@ -557,7 +884,8 @@ out1: | |||
557 | 884 | ||
558 | static struct ethtool_ops ax88772_ethtool_ops = { | 885 | static struct ethtool_ops ax88772_ethtool_ops = { |
559 | .get_drvinfo = asix_get_drvinfo, | 886 | .get_drvinfo = asix_get_drvinfo, |
560 | .get_link = ethtool_op_get_link, | 887 | .get_link = asix_get_link, |
888 | .nway_reset = asix_nway_reset, | ||
561 | .get_msglevel = usbnet_get_msglevel, | 889 | .get_msglevel = usbnet_get_msglevel, |
562 | .set_msglevel = usbnet_set_msglevel, | 890 | .set_msglevel = usbnet_set_msglevel, |
563 | .get_wol = asix_get_wol, | 891 | .get_wol = asix_get_wol, |
@@ -568,10 +896,37 @@ static struct ethtool_ops ax88772_ethtool_ops = { | |||
568 | .set_settings = asix_set_settings, | 896 | .set_settings = asix_set_settings, |
569 | }; | 897 | }; |
570 | 898 | ||
899 | static int ax88772_link_reset(struct usbnet *dev) | ||
900 | { | ||
901 | u16 mode; | ||
902 | struct ethtool_cmd ecmd; | ||
903 | |||
904 | mii_check_media(&dev->mii, 1, 1); | ||
905 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
906 | mode = AX88772_MEDIUM_DEFAULT; | ||
907 | |||
908 | if (ecmd.speed != SPEED_100) | ||
909 | mode &= ~AX_MEDIUM_PS; | ||
910 | |||
911 | if (ecmd.duplex != DUPLEX_FULL) | ||
912 | mode &= ~AX_MEDIUM_FD; | ||
913 | |||
914 | devdbg(dev, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode); | ||
915 | |||
916 | asix_write_medium_mode(dev, mode); | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
571 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | 921 | static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) |
572 | { | 922 | { |
573 | int ret; | 923 | int ret; |
574 | void *buf; | 924 | void *buf; |
925 | u16 rx_ctl; | ||
926 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
927 | u32 phyid; | ||
928 | |||
929 | data->eeprom_len = AX88772_EEPROM_LEN; | ||
575 | 930 | ||
576 | usbnet_get_endpoints(dev,intf); | 931 | usbnet_get_endpoints(dev,intf); |
577 | 932 | ||
@@ -582,13 +937,12 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
582 | goto out1; | 937 | goto out1; |
583 | } | 938 | } |
584 | 939 | ||
585 | if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, | 940 | if ((ret = asix_write_gpio(dev, |
586 | 0x00B0, 0, 0, buf)) < 0) | 941 | AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) |
587 | goto out2; | 942 | goto out2; |
588 | 943 | ||
589 | msleep(5); | ||
590 | if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, | 944 | if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, |
591 | 0x0001, 0, 0, buf)) < 0) { | 945 | 0x0000, 0, 0, buf)) < 0) { |
592 | dbg("Select PHY #1 failed: %d", ret); | 946 | dbg("Select PHY #1 failed: %d", ret); |
593 | goto out2; | 947 | goto out2; |
594 | } | 948 | } |
@@ -605,36 +959,34 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
605 | goto out2; | 959 | goto out2; |
606 | 960 | ||
607 | msleep(150); | 961 | msleep(150); |
608 | if ((ret = asix_write_rx_ctl(dev, 0x00)) < 0) | 962 | rx_ctl = asix_read_rx_ctl(dev); |
963 | dbg("RX_CTL is 0x%04x after software reset", rx_ctl); | ||
964 | if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0) | ||
609 | goto out2; | 965 | goto out2; |
610 | 966 | ||
967 | rx_ctl = asix_read_rx_ctl(dev); | ||
968 | dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl); | ||
969 | |||
611 | /* Get the MAC address */ | 970 | /* Get the MAC address */ |
612 | memset(buf, 0, ETH_ALEN); | 971 | memset(buf, 0, ETH_ALEN); |
613 | if ((ret = asix_read_cmd(dev, AX88772_CMD_READ_NODE_ID, | 972 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, |
614 | 0, 0, ETH_ALEN, buf)) < 0) { | 973 | 0, 0, ETH_ALEN, buf)) < 0) { |
615 | dbg("Failed to read MAC address: %d", ret); | 974 | dbg("Failed to read MAC address: %d", ret); |
616 | goto out2; | 975 | goto out2; |
617 | } | 976 | } |
618 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); | 977 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); |
619 | 978 | ||
620 | if ((ret = asix_set_sw_mii(dev)) < 0) | ||
621 | goto out2; | ||
622 | |||
623 | if (((ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG, | ||
624 | 0x0010, 2, 2, buf)) < 0) | ||
625 | || (*((u16 *)buf) != 0x003b)) { | ||
626 | dbg("Read PHY register 2 must be 0x3b00: %d", ret); | ||
627 | goto out2; | ||
628 | } | ||
629 | |||
630 | /* Initialize MII structure */ | 979 | /* Initialize MII structure */ |
631 | dev->mii.dev = dev->net; | 980 | dev->mii.dev = dev->net; |
632 | dev->mii.mdio_read = asix_mdio_read; | 981 | dev->mii.mdio_read = asix_mdio_read; |
633 | dev->mii.mdio_write = asix_mdio_write; | 982 | dev->mii.mdio_write = asix_mdio_write; |
634 | dev->mii.phy_id_mask = 0xff; | 983 | dev->mii.phy_id_mask = 0x1f; |
635 | dev->mii.reg_num_mask = 0xff; | 984 | dev->mii.reg_num_mask = 0x1f; |
636 | dev->net->do_ioctl = asix_ioctl; | 985 | dev->net->do_ioctl = asix_ioctl; |
637 | dev->mii.phy_id = asix_get_phyid(dev); | 986 | dev->mii.phy_id = asix_get_phy_addr(dev); |
987 | |||
988 | phyid = asix_get_phyid(dev); | ||
989 | dbg("PHYID=0x%08x", phyid); | ||
638 | 990 | ||
639 | if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) | 991 | if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) |
640 | goto out2; | 992 | goto out2; |
@@ -649,16 +1001,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
649 | dev->net->set_multicast_list = asix_set_multicast; | 1001 | dev->net->set_multicast_list = asix_set_multicast; |
650 | dev->net->ethtool_ops = &ax88772_ethtool_ops; | 1002 | dev->net->ethtool_ops = &ax88772_ethtool_ops; |
651 | 1003 | ||
652 | asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | 1004 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); |
653 | asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE, | 1005 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, |
654 | ADVERTISE_ALL | ADVERTISE_CSMA); | 1006 | ADVERTISE_ALL | ADVERTISE_CSMA); |
655 | mii_nway_restart(&dev->mii); | 1007 | mii_nway_restart(&dev->mii); |
656 | 1008 | ||
657 | if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, | 1009 | if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0) |
658 | AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) { | ||
659 | dbg("Write medium mode register: %d", ret); | ||
660 | goto out2; | 1010 | goto out2; |
661 | } | ||
662 | 1011 | ||
663 | if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0, | 1012 | if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0, |
664 | AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, | 1013 | AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, |
@@ -666,13 +1015,17 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) | |||
666 | dbg("Write IPG,IPG1,IPG2 failed: %d", ret); | 1015 | dbg("Write IPG,IPG1,IPG2 failed: %d", ret); |
667 | goto out2; | 1016 | goto out2; |
668 | } | 1017 | } |
669 | if ((ret = asix_set_hw_mii(dev)) < 0) | ||
670 | goto out2; | ||
671 | 1018 | ||
672 | /* Set RX_CTL to default values with 2k buffer, and enable cactus */ | 1019 | /* Set RX_CTL to default values with 2k buffer, and enable cactus */ |
673 | if ((ret = asix_write_rx_ctl(dev, 0x0088)) < 0) | 1020 | if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) |
674 | goto out2; | 1021 | goto out2; |
675 | 1022 | ||
1023 | rx_ctl = asix_read_rx_ctl(dev); | ||
1024 | dbg("RX_CTL is 0x%04x after all initializations", rx_ctl); | ||
1025 | |||
1026 | rx_ctl = asix_read_medium_status(dev); | ||
1027 | dbg("Medium Status is 0x%04x after all initializations", rx_ctl); | ||
1028 | |||
676 | kfree(buf); | 1029 | kfree(buf); |
677 | 1030 | ||
678 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ | 1031 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ |
@@ -690,120 +1043,285 @@ out1: | |||
690 | return ret; | 1043 | return ret; |
691 | } | 1044 | } |
692 | 1045 | ||
693 | static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 1046 | static struct ethtool_ops ax88178_ethtool_ops = { |
1047 | .get_drvinfo = asix_get_drvinfo, | ||
1048 | .get_link = asix_get_link, | ||
1049 | .nway_reset = asix_nway_reset, | ||
1050 | .get_msglevel = usbnet_get_msglevel, | ||
1051 | .set_msglevel = usbnet_set_msglevel, | ||
1052 | .get_wol = asix_get_wol, | ||
1053 | .set_wol = asix_set_wol, | ||
1054 | .get_eeprom_len = asix_get_eeprom_len, | ||
1055 | .get_eeprom = asix_get_eeprom, | ||
1056 | .get_settings = asix_get_settings, | ||
1057 | .set_settings = asix_set_settings, | ||
1058 | }; | ||
1059 | |||
1060 | static int marvell_phy_init(struct usbnet *dev) | ||
694 | { | 1061 | { |
695 | u8 *head; | 1062 | struct asix_data *data = (struct asix_data *)&dev->data; |
696 | u32 header; | 1063 | u16 reg; |
697 | char *packet; | ||
698 | struct sk_buff *ax_skb; | ||
699 | u16 size; | ||
700 | 1064 | ||
701 | head = (u8 *) skb->data; | 1065 | devdbg(dev,"marvell_phy_init()"); |
702 | memcpy(&header, head, sizeof(header)); | ||
703 | le32_to_cpus(&header); | ||
704 | packet = head + sizeof(header); | ||
705 | 1066 | ||
706 | skb_pull(skb, 4); | 1067 | reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS); |
1068 | devdbg(dev,"MII_MARVELL_STATUS = 0x%04x", reg); | ||
707 | 1069 | ||
708 | while (skb->len > 0) { | 1070 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL, |
709 | if ((short)(header & 0x0000ffff) != | 1071 | MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY); |
710 | ~((short)((header & 0xffff0000) >> 16))) { | ||
711 | devdbg(dev,"header length data is error"); | ||
712 | } | ||
713 | /* get the packet length */ | ||
714 | size = (u16) (header & 0x0000ffff); | ||
715 | 1072 | ||
716 | if ((skb->len) - ((size + 1) & 0xfffe) == 0) | 1073 | if (data->ledmode) { |
717 | return 2; | 1074 | reg = asix_mdio_read(dev->net, dev->mii.phy_id, |
718 | if (size > ETH_FRAME_LEN) { | 1075 | MII_MARVELL_LED_CTRL); |
719 | devdbg(dev,"invalid rx length %d", size); | 1076 | devdbg(dev,"MII_MARVELL_LED_CTRL (1) = 0x%04x", reg); |
720 | return 0; | ||
721 | } | ||
722 | ax_skb = skb_clone(skb, GFP_ATOMIC); | ||
723 | if (ax_skb) { | ||
724 | ax_skb->len = size; | ||
725 | ax_skb->data = packet; | ||
726 | ax_skb->tail = packet + size; | ||
727 | usbnet_skb_return(dev, ax_skb); | ||
728 | } else { | ||
729 | return 0; | ||
730 | } | ||
731 | 1077 | ||
732 | skb_pull(skb, (size + 1) & 0xfffe); | 1078 | reg &= 0xf8ff; |
1079 | reg |= (1 + 0x0100); | ||
1080 | asix_mdio_write(dev->net, dev->mii.phy_id, | ||
1081 | MII_MARVELL_LED_CTRL, reg); | ||
733 | 1082 | ||
734 | if (skb->len == 0) | 1083 | reg = asix_mdio_read(dev->net, dev->mii.phy_id, |
735 | break; | 1084 | MII_MARVELL_LED_CTRL); |
1085 | devdbg(dev,"MII_MARVELL_LED_CTRL (2) = 0x%04x", reg); | ||
1086 | reg &= 0xfc0f; | ||
1087 | } | ||
736 | 1088 | ||
737 | head = (u8 *) skb->data; | 1089 | return 0; |
738 | memcpy(&header, head, sizeof(header)); | 1090 | } |
739 | le32_to_cpus(&header); | 1091 | |
740 | packet = head + sizeof(header); | 1092 | static int marvell_led_status(struct usbnet *dev, u16 speed) |
741 | skb_pull(skb, 4); | 1093 | { |
1094 | u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL); | ||
1095 | |||
1096 | devdbg(dev, "marvell_led_status() read 0x%04x", reg); | ||
1097 | |||
1098 | /* Clear out the center LED bits - 0x03F0 */ | ||
1099 | reg &= 0xfc0f; | ||
1100 | |||
1101 | switch (speed) { | ||
1102 | case SPEED_1000: | ||
1103 | reg |= 0x03e0; | ||
1104 | break; | ||
1105 | case SPEED_100: | ||
1106 | reg |= 0x03b0; | ||
1107 | break; | ||
1108 | default: | ||
1109 | reg |= 0x02f0; | ||
742 | } | 1110 | } |
743 | 1111 | ||
744 | if (skb->len < 0) { | 1112 | devdbg(dev, "marvell_led_status() writing 0x%04x", reg); |
745 | devdbg(dev,"invalid rx length %d", skb->len); | 1113 | asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg); |
746 | return 0; | 1114 | |
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | static int ax88178_link_reset(struct usbnet *dev) | ||
1119 | { | ||
1120 | u16 mode; | ||
1121 | struct ethtool_cmd ecmd; | ||
1122 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1123 | |||
1124 | devdbg(dev,"ax88178_link_reset()"); | ||
1125 | |||
1126 | mii_check_media(&dev->mii, 1, 1); | ||
1127 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
1128 | mode = AX88178_MEDIUM_DEFAULT; | ||
1129 | |||
1130 | if (ecmd.speed == SPEED_1000) | ||
1131 | mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK; | ||
1132 | else if (ecmd.speed == SPEED_100) | ||
1133 | mode |= AX_MEDIUM_PS; | ||
1134 | else | ||
1135 | mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); | ||
1136 | |||
1137 | if (ecmd.duplex == DUPLEX_FULL) | ||
1138 | mode |= AX_MEDIUM_FD; | ||
1139 | else | ||
1140 | mode &= ~AX_MEDIUM_FD; | ||
1141 | |||
1142 | devdbg(dev, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode); | ||
1143 | |||
1144 | asix_write_medium_mode(dev, mode); | ||
1145 | |||
1146 | if (data->phymode == PHY_MODE_MARVELL && data->ledmode) | ||
1147 | marvell_led_status(dev, ecmd.speed); | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | static void ax88178_set_mfb(struct usbnet *dev) | ||
1153 | { | ||
1154 | u16 mfb = AX_RX_CTL_MFB_16384; | ||
1155 | u16 rxctl; | ||
1156 | u16 medium; | ||
1157 | int old_rx_urb_size = dev->rx_urb_size; | ||
1158 | |||
1159 | if (dev->hard_mtu < 2048) { | ||
1160 | dev->rx_urb_size = 2048; | ||
1161 | mfb = AX_RX_CTL_MFB_2048; | ||
1162 | } else if (dev->hard_mtu < 4096) { | ||
1163 | dev->rx_urb_size = 4096; | ||
1164 | mfb = AX_RX_CTL_MFB_4096; | ||
1165 | } else if (dev->hard_mtu < 8192) { | ||
1166 | dev->rx_urb_size = 8192; | ||
1167 | mfb = AX_RX_CTL_MFB_8192; | ||
1168 | } else if (dev->hard_mtu < 16384) { | ||
1169 | dev->rx_urb_size = 16384; | ||
1170 | mfb = AX_RX_CTL_MFB_16384; | ||
747 | } | 1171 | } |
748 | return 1; | 1172 | |
1173 | rxctl = asix_read_rx_ctl(dev); | ||
1174 | asix_write_rx_ctl(dev, (rxctl & ~AX_RX_CTL_MFB_16384) | mfb); | ||
1175 | |||
1176 | medium = asix_read_medium_status(dev); | ||
1177 | if (dev->net->mtu > 1500) | ||
1178 | medium |= AX_MEDIUM_JFE; | ||
1179 | else | ||
1180 | medium &= ~AX_MEDIUM_JFE; | ||
1181 | asix_write_medium_mode(dev, medium); | ||
1182 | |||
1183 | if (dev->rx_urb_size > old_rx_urb_size) | ||
1184 | usbnet_unlink_rx_urbs(dev); | ||
749 | } | 1185 | } |
750 | 1186 | ||
751 | static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | 1187 | static int ax88178_change_mtu(struct net_device *net, int new_mtu) |
752 | gfp_t flags) | ||
753 | { | 1188 | { |
754 | int padlen; | 1189 | struct usbnet *dev = netdev_priv(net); |
755 | int headroom = skb_headroom(skb); | 1190 | int ll_mtu = new_mtu + net->hard_header_len + 4; |
756 | int tailroom = skb_tailroom(skb); | ||
757 | u32 packet_len; | ||
758 | u32 padbytes = 0xffff0000; | ||
759 | 1191 | ||
760 | padlen = ((skb->len + 4) % 512) ? 0 : 4; | 1192 | devdbg(dev, "ax88178_change_mtu() new_mtu=%d", new_mtu); |
761 | 1193 | ||
762 | if ((!skb_cloned(skb)) | 1194 | if (new_mtu <= 0 || ll_mtu > 16384) |
763 | && ((headroom + tailroom) >= (4 + padlen))) { | 1195 | return -EINVAL; |
764 | if ((headroom < 4) || (tailroom < padlen)) { | 1196 | |
765 | skb->data = memmove(skb->head + 4, skb->data, skb->len); | 1197 | if ((ll_mtu % dev->maxpacket) == 0) |
766 | skb->tail = skb->data + skb->len; | 1198 | return -EDOM; |
767 | } | 1199 | |
1200 | net->mtu = new_mtu; | ||
1201 | dev->hard_mtu = net->mtu + net->hard_header_len; | ||
1202 | ax88178_set_mfb(dev); | ||
1203 | |||
1204 | return 0; | ||
1205 | } | ||
1206 | |||
1207 | static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) | ||
1208 | { | ||
1209 | struct asix_data *data = (struct asix_data *)&dev->data; | ||
1210 | int ret; | ||
1211 | void *buf; | ||
1212 | u16 eeprom; | ||
1213 | int gpio0 = 0; | ||
1214 | u32 phyid; | ||
1215 | |||
1216 | usbnet_get_endpoints(dev,intf); | ||
1217 | |||
1218 | buf = kmalloc(6, GFP_KERNEL); | ||
1219 | if(!buf) { | ||
1220 | dbg ("Cannot allocate memory for buffer"); | ||
1221 | ret = -ENOMEM; | ||
1222 | goto out1; | ||
1223 | } | ||
1224 | |||
1225 | eeprom = 0; | ||
1226 | asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &eeprom); | ||
1227 | dbg("GPIO Status: 0x%04x", eeprom); | ||
1228 | |||
1229 | asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL); | ||
1230 | asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom); | ||
1231 | asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL); | ||
1232 | |||
1233 | dbg("EEPROM index 0x17 is 0x%04x", eeprom); | ||
1234 | |||
1235 | if (eeprom == 0xffff) { | ||
1236 | data->phymode = PHY_MODE_MARVELL; | ||
1237 | data->ledmode = 0; | ||
1238 | gpio0 = 1; | ||
768 | } else { | 1239 | } else { |
769 | struct sk_buff *skb2; | 1240 | data->phymode = eeprom & 7; |
770 | skb2 = skb_copy_expand(skb, 4, padlen, flags); | 1241 | data->ledmode = eeprom >> 8; |
771 | dev_kfree_skb_any(skb); | 1242 | gpio0 = (eeprom & 0x80) ? 0 : 1; |
772 | skb = skb2; | ||
773 | if (!skb) | ||
774 | return NULL; | ||
775 | } | 1243 | } |
1244 | dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); | ||
776 | 1245 | ||
777 | skb_push(skb, 4); | 1246 | asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); |
778 | packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); | 1247 | if ((eeprom >> 8) != 1) { |
779 | memcpy(skb->data, &packet_len, sizeof(packet_len)); | 1248 | asix_write_gpio(dev, 0x003c, 30); |
1249 | asix_write_gpio(dev, 0x001c, 300); | ||
1250 | asix_write_gpio(dev, 0x003c, 30); | ||
1251 | } else { | ||
1252 | dbg("gpio phymode == 1 path"); | ||
1253 | asix_write_gpio(dev, AX_GPIO_GPO1EN, 30); | ||
1254 | asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); | ||
1255 | } | ||
780 | 1256 | ||
781 | if ((skb->len % 512) == 0) { | 1257 | asix_sw_reset(dev, 0); |
782 | memcpy( skb->tail, &padbytes, sizeof(padbytes)); | 1258 | msleep(150); |
783 | skb_put(skb, sizeof(padbytes)); | 1259 | |
1260 | asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); | ||
1261 | msleep(150); | ||
1262 | |||
1263 | asix_write_rx_ctl(dev, 0); | ||
1264 | |||
1265 | /* Get the MAC address */ | ||
1266 | memset(buf, 0, ETH_ALEN); | ||
1267 | if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, | ||
1268 | 0, 0, ETH_ALEN, buf)) < 0) { | ||
1269 | dbg("Failed to read MAC address: %d", ret); | ||
1270 | goto out2; | ||
784 | } | 1271 | } |
785 | return skb; | 1272 | memcpy(dev->net->dev_addr, buf, ETH_ALEN); |
786 | } | ||
787 | 1273 | ||
788 | static int ax88772_link_reset(struct usbnet *dev) | 1274 | /* Initialize MII structure */ |
789 | { | 1275 | dev->mii.dev = dev->net; |
790 | u16 lpa; | 1276 | dev->mii.mdio_read = asix_mdio_read; |
791 | u16 adv; | 1277 | dev->mii.mdio_write = asix_mdio_write; |
792 | u16 res; | 1278 | dev->mii.phy_id_mask = 0x1f; |
793 | u16 mode; | 1279 | dev->mii.reg_num_mask = 0xff; |
1280 | dev->mii.supports_gmii = 1; | ||
1281 | dev->net->do_ioctl = asix_ioctl; | ||
1282 | dev->mii.phy_id = asix_get_phy_addr(dev); | ||
1283 | dev->net->set_multicast_list = asix_set_multicast; | ||
1284 | dev->net->ethtool_ops = &ax88178_ethtool_ops; | ||
1285 | dev->net->change_mtu = &ax88178_change_mtu; | ||
794 | 1286 | ||
795 | mode = AX88772_MEDIUM_DEFAULT; | 1287 | phyid = asix_get_phyid(dev); |
796 | lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA); | 1288 | dbg("PHYID=0x%08x", phyid); |
797 | adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE); | 1289 | |
798 | res = mii_nway_result(lpa|adv); | 1290 | if (data->phymode == PHY_MODE_MARVELL) { |
1291 | marvell_phy_init(dev); | ||
1292 | msleep(60); | ||
1293 | } | ||
1294 | |||
1295 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, | ||
1296 | BMCR_RESET | BMCR_ANENABLE); | ||
1297 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
1298 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); | ||
1299 | asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, | ||
1300 | ADVERTISE_1000FULL); | ||
1301 | |||
1302 | mii_nway_restart(&dev->mii); | ||
799 | 1303 | ||
800 | if ((res & LPA_DUPLEX) == 0) | 1304 | if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0) |
801 | mode &= ~AX88772_MEDIUM_FULL_DUPLEX; | 1305 | goto out2; |
802 | if ((res & LPA_100) == 0) | 1306 | |
803 | mode &= ~AX88772_MEDIUM_100MB; | 1307 | if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) |
804 | asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); | 1308 | goto out2; |
1309 | |||
1310 | kfree(buf); | ||
1311 | |||
1312 | /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ | ||
1313 | if (dev->driver_info->flags & FLAG_FRAMING_AX) { | ||
1314 | /* hard_mtu is still the default - the device does not support | ||
1315 | jumbo eth frames */ | ||
1316 | dev->rx_urb_size = 2048; | ||
1317 | } | ||
805 | 1318 | ||
806 | return 0; | 1319 | return 0; |
1320 | |||
1321 | out2: | ||
1322 | kfree(buf); | ||
1323 | out1: | ||
1324 | return ret; | ||
807 | } | 1325 | } |
808 | 1326 | ||
809 | static const struct driver_info ax8817x_info = { | 1327 | static const struct driver_info ax8817x_info = { |
@@ -853,8 +1371,19 @@ static const struct driver_info ax88772_info = { | |||
853 | .link_reset = ax88772_link_reset, | 1371 | .link_reset = ax88772_link_reset, |
854 | .reset = ax88772_link_reset, | 1372 | .reset = ax88772_link_reset, |
855 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | 1373 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, |
856 | .rx_fixup = ax88772_rx_fixup, | 1374 | .rx_fixup = asix_rx_fixup, |
857 | .tx_fixup = ax88772_tx_fixup, | 1375 | .tx_fixup = asix_tx_fixup, |
1376 | }; | ||
1377 | |||
1378 | static const struct driver_info ax88178_info = { | ||
1379 | .description = "ASIX AX88178 USB 2.0 Ethernet", | ||
1380 | .bind = ax88178_bind, | ||
1381 | .status = asix_status, | ||
1382 | .link_reset = ax88178_link_reset, | ||
1383 | .reset = ax88178_link_reset, | ||
1384 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
1385 | .rx_fixup = asix_rx_fixup, | ||
1386 | .tx_fixup = asix_tx_fixup, | ||
858 | }; | 1387 | }; |
859 | 1388 | ||
860 | static const struct usb_device_id products [] = { | 1389 | static const struct usb_device_id products [] = { |
@@ -913,7 +1442,7 @@ static const struct usb_device_id products [] = { | |||
913 | }, { | 1442 | }, { |
914 | // ASIX AX88178 10/100/1000 | 1443 | // ASIX AX88178 10/100/1000 |
915 | USB_DEVICE (0x0b95, 0x1780), | 1444 | USB_DEVICE (0x0b95, 0x1780), |
916 | .driver_info = (unsigned long) &ax88772_info, | 1445 | .driver_info = (unsigned long) &ax88178_info, |
917 | }, { | 1446 | }, { |
918 | // Linksys USB200M Rev 2 | 1447 | // Linksys USB200M Rev 2 |
919 | USB_DEVICE (0x13b1, 0x0018), | 1448 | USB_DEVICE (0x13b1, 0x0018), |
@@ -922,6 +1451,14 @@ static const struct usb_device_id products [] = { | |||
922 | // 0Q0 cable ethernet | 1451 | // 0Q0 cable ethernet |
923 | USB_DEVICE (0x1557, 0x7720), | 1452 | USB_DEVICE (0x1557, 0x7720), |
924 | .driver_info = (unsigned long) &ax88772_info, | 1453 | .driver_info = (unsigned long) &ax88772_info, |
1454 | }, { | ||
1455 | // DLink DUB-E100 H/W Ver B1 | ||
1456 | USB_DEVICE (0x07d1, 0x3c05), | ||
1457 | .driver_info = (unsigned long) &ax88772_info, | ||
1458 | }, { | ||
1459 | // Linksys USB1000 | ||
1460 | USB_DEVICE (0x1737, 0x0039), | ||
1461 | .driver_info = (unsigned long) &ax88178_info, | ||
925 | }, | 1462 | }, |
926 | { }, // END | 1463 | { }, // END |
927 | }; | 1464 | }; |
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c index a9b6eeac3e3f..301baa72bac7 100644 --- a/drivers/usb/net/net1080.c +++ b/drivers/usb/net/net1080.c | |||
@@ -498,25 +498,24 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
498 | static struct sk_buff * | 498 | static struct sk_buff * |
499 | net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | 499 | net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) |
500 | { | 500 | { |
501 | int padlen; | ||
502 | struct sk_buff *skb2; | 501 | struct sk_buff *skb2; |
503 | struct nc_header *header = NULL; | 502 | struct nc_header *header = NULL; |
504 | struct nc_trailer *trailer = NULL; | 503 | struct nc_trailer *trailer = NULL; |
504 | int padlen = sizeof (struct nc_trailer); | ||
505 | int len = skb->len; | 505 | int len = skb->len; |
506 | 506 | ||
507 | padlen = ((len + sizeof (struct nc_header) | 507 | if (!((len + padlen + sizeof (struct nc_header)) & 0x01)) |
508 | + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1; | 508 | padlen++; |
509 | if (!skb_cloned(skb)) { | 509 | if (!skb_cloned(skb)) { |
510 | int headroom = skb_headroom(skb); | 510 | int headroom = skb_headroom(skb); |
511 | int tailroom = skb_tailroom(skb); | 511 | int tailroom = skb_tailroom(skb); |
512 | 512 | ||
513 | if ((padlen + sizeof (struct nc_trailer)) <= tailroom | 513 | if (padlen <= tailroom && |
514 | && sizeof (struct nc_header) <= headroom) | 514 | sizeof(struct nc_header) <= headroom) |
515 | /* There's enough head and tail room */ | 515 | /* There's enough head and tail room */ |
516 | goto encapsulate; | 516 | goto encapsulate; |
517 | 517 | ||
518 | if ((sizeof (struct nc_header) + padlen | 518 | if ((sizeof (struct nc_header) + padlen) < |
519 | + sizeof (struct nc_trailer)) < | ||
520 | (headroom + tailroom)) { | 519 | (headroom + tailroom)) { |
521 | /* There's enough total room, so just readjust */ | 520 | /* There's enough total room, so just readjust */ |
522 | skb->data = memmove(skb->head | 521 | skb->data = memmove(skb->head |
@@ -530,7 +529,7 @@ net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | |||
530 | /* Create a new skb to use with the correct size */ | 529 | /* Create a new skb to use with the correct size */ |
531 | skb2 = skb_copy_expand(skb, | 530 | skb2 = skb_copy_expand(skb, |
532 | sizeof (struct nc_header), | 531 | sizeof (struct nc_header), |
533 | sizeof (struct nc_trailer) + padlen, | 532 | padlen, |
534 | flags); | 533 | flags); |
535 | dev_kfree_skb_any(skb); | 534 | dev_kfree_skb_any(skb); |
536 | if (!skb2) | 535 | if (!skb2) |
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index ab21f960d255..b8e25af13f02 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
@@ -619,7 +619,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
619 | switch (urb->status) { | 619 | switch (urb->status) { |
620 | case 0: | 620 | case 0: |
621 | break; | 621 | break; |
622 | case -ETIMEDOUT: | 622 | case -ETIME: |
623 | if (netif_msg_rx_err(pegasus)) | 623 | if (netif_msg_rx_err(pegasus)) |
624 | pr_debug("%s: reset MAC\n", net->name); | 624 | pr_debug("%s: reset MAC\n", net->name); |
625 | pegasus->flags &= ~PEGASUS_RX_BUSY; | 625 | pegasus->flags &= ~PEGASUS_RX_BUSY; |
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index a72685b96061..2364c2099387 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c | |||
@@ -438,7 +438,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
438 | break; | 438 | break; |
439 | case -ENOENT: | 439 | case -ENOENT: |
440 | return; /* the urb is in unlink state */ | 440 | return; /* the urb is in unlink state */ |
441 | case -ETIMEDOUT: | 441 | case -ETIME: |
442 | warn("may be reset is needed?.."); | 442 | warn("may be reset is needed?.."); |
443 | goto goon; | 443 | goto goon; |
444 | default: | 444 | default: |
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 54183e173a6d..98a522f1e264 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c | |||
@@ -61,8 +61,11 @@ | |||
61 | * let the USB host controller be busy for 5msec or more before an irq | 61 | * let the USB host controller be busy for 5msec or more before an irq |
62 | * is required, under load. Jumbograms change the equation. | 62 | * is required, under load. Jumbograms change the equation. |
63 | */ | 63 | */ |
64 | #define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4) | 64 | #define RX_MAX_QUEUE_MEMORY (60 * 1518) |
65 | #define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4) | 65 | #define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ |
66 | (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4) | ||
67 | #define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ | ||
68 | (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4) | ||
66 | 69 | ||
67 | // reawaken network queue this soon after stopping; else watchdog barks | 70 | // reawaken network queue this soon after stopping; else watchdog barks |
68 | #define TX_TIMEOUT_JIFFIES (5*HZ) | 71 | #define TX_TIMEOUT_JIFFIES (5*HZ) |
@@ -227,13 +230,23 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu) | |||
227 | { | 230 | { |
228 | struct usbnet *dev = netdev_priv(net); | 231 | struct usbnet *dev = netdev_priv(net); |
229 | int ll_mtu = new_mtu + net->hard_header_len; | 232 | int ll_mtu = new_mtu + net->hard_header_len; |
233 | int old_hard_mtu = dev->hard_mtu; | ||
234 | int old_rx_urb_size = dev->rx_urb_size; | ||
230 | 235 | ||
231 | if (new_mtu <= 0 || ll_mtu > dev->hard_mtu) | 236 | if (new_mtu <= 0) |
232 | return -EINVAL; | 237 | return -EINVAL; |
233 | // no second zero-length packet read wanted after mtu-sized packets | 238 | // no second zero-length packet read wanted after mtu-sized packets |
234 | if ((ll_mtu % dev->maxpacket) == 0) | 239 | if ((ll_mtu % dev->maxpacket) == 0) |
235 | return -EDOM; | 240 | return -EDOM; |
236 | net->mtu = new_mtu; | 241 | net->mtu = new_mtu; |
242 | |||
243 | dev->hard_mtu = net->mtu + net->hard_header_len; | ||
244 | if (dev->rx_urb_size == old_hard_mtu) { | ||
245 | dev->rx_urb_size = dev->hard_mtu; | ||
246 | if (dev->rx_urb_size > old_rx_urb_size) | ||
247 | usbnet_unlink_rx_urbs(dev); | ||
248 | } | ||
249 | |||
237 | return 0; | 250 | return 0; |
238 | } | 251 | } |
239 | 252 | ||
@@ -412,9 +425,9 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs) | |||
412 | // we get controller i/o faults during khubd disconnect() delays. | 425 | // we get controller i/o faults during khubd disconnect() delays. |
413 | // throttle down resubmits, to avoid log floods; just temporarily, | 426 | // throttle down resubmits, to avoid log floods; just temporarily, |
414 | // so we still recover when the fault isn't a khubd delay. | 427 | // so we still recover when the fault isn't a khubd delay. |
415 | case -EPROTO: // ehci | 428 | case -EPROTO: |
416 | case -ETIMEDOUT: // ohci | 429 | case -ETIME: |
417 | case -EILSEQ: // uhci | 430 | case -EILSEQ: |
418 | dev->stats.rx_errors++; | 431 | dev->stats.rx_errors++; |
419 | if (!timer_pending (&dev->delay)) { | 432 | if (!timer_pending (&dev->delay)) { |
420 | mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); | 433 | mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); |
@@ -521,6 +534,17 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) | |||
521 | return count; | 534 | return count; |
522 | } | 535 | } |
523 | 536 | ||
537 | // Flush all pending rx urbs | ||
538 | // minidrivers may need to do this when the MTU changes | ||
539 | |||
540 | void usbnet_unlink_rx_urbs(struct usbnet *dev) | ||
541 | { | ||
542 | if (netif_running(dev->net)) { | ||
543 | (void) unlink_urbs (dev, &dev->rxq); | ||
544 | tasklet_schedule(&dev->bh); | ||
545 | } | ||
546 | } | ||
547 | EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs); | ||
524 | 548 | ||
525 | /*-------------------------------------------------------------------------*/ | 549 | /*-------------------------------------------------------------------------*/ |
526 | 550 | ||
@@ -629,7 +653,7 @@ static int usbnet_open (struct net_device *net) | |||
629 | 653 | ||
630 | devinfo (dev, "open: enable queueing " | 654 | devinfo (dev, "open: enable queueing " |
631 | "(rx %d, tx %d) mtu %d %s framing", | 655 | "(rx %d, tx %d) mtu %d %s framing", |
632 | RX_QLEN (dev), TX_QLEN (dev), dev->net->mtu, | 656 | (int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu, |
633 | framing); | 657 | framing); |
634 | } | 658 | } |
635 | 659 | ||
@@ -797,9 +821,9 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs) | |||
797 | 821 | ||
798 | // like rx, tx gets controller i/o faults during khubd delays | 822 | // like rx, tx gets controller i/o faults during khubd delays |
799 | // and so it uses the same throttling mechanism. | 823 | // and so it uses the same throttling mechanism. |
800 | case -EPROTO: // ehci | 824 | case -EPROTO: |
801 | case -ETIMEDOUT: // ohci | 825 | case -ETIME: |
802 | case -EILSEQ: // uhci | 826 | case -EILSEQ: |
803 | if (!timer_pending (&dev->delay)) { | 827 | if (!timer_pending (&dev->delay)) { |
804 | mod_timer (&dev->delay, | 828 | mod_timer (&dev->delay, |
805 | jiffies + THROTTLE_JIFFIES); | 829 | jiffies + THROTTLE_JIFFIES); |
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h index 89fc4958eecf..c0746f0454af 100644 --- a/drivers/usb/net/usbnet.h +++ b/drivers/usb/net/usbnet.h | |||
@@ -166,6 +166,7 @@ struct skb_data { /* skb->cb is one of these */ | |||
166 | extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *); | 166 | extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *); |
167 | extern void usbnet_defer_kevent (struct usbnet *, int); | 167 | extern void usbnet_defer_kevent (struct usbnet *, int); |
168 | extern void usbnet_skb_return (struct usbnet *, struct sk_buff *); | 168 | extern void usbnet_skb_return (struct usbnet *, struct sk_buff *); |
169 | extern void usbnet_unlink_rx_urbs(struct usbnet *); | ||
169 | 170 | ||
170 | extern u32 usbnet_get_msglevel (struct net_device *); | 171 | extern u32 usbnet_get_msglevel (struct net_device *); |
171 | extern void usbnet_set_msglevel (struct net_device *, u32); | 172 | extern void usbnet_set_msglevel (struct net_device *, u32); |
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index f5b9438c94f0..5076b9d97057 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -53,6 +53,15 @@ config USB_SERIAL_GENERIC | |||
53 | support" be compiled as a module for this driver to be used | 53 | support" be compiled as a module for this driver to be used |
54 | properly. | 54 | properly. |
55 | 55 | ||
56 | config USB_SERIAL_AIRCABLE | ||
57 | tristate "AIRcable USB Bluetooth Dongle Driver (EXPERIMENTAL)" | ||
58 | depends on USB_SERIAL && EXPERIMENTAL | ||
59 | help | ||
60 | Say Y here if you want to use AIRcable USB Bluetoot Dongle. | ||
61 | |||
62 | To compile this driver as a module, choose M here: the module | ||
63 | will be called aircable. | ||
64 | |||
56 | config USB_SERIAL_AIRPRIME | 65 | config USB_SERIAL_AIRPRIME |
57 | tristate "USB AirPrime CDMA Wireless Driver" | 66 | tristate "USB AirPrime CDMA Wireless Driver" |
58 | depends on USB_SERIAL | 67 | depends on USB_SERIAL |
@@ -413,6 +422,21 @@ config USB_SERIAL_MCT_U232 | |||
413 | To compile this driver as a module, choose M here: the | 422 | To compile this driver as a module, choose M here: the |
414 | module will be called mct_u232. | 423 | module will be called mct_u232. |
415 | 424 | ||
425 | config USB_SERIAL_MOS7840 | ||
426 | tristate "USB Moschip 7840/7820 USB Serial Driver" | ||
427 | depends on USB_SERIAL | ||
428 | ---help--- | ||
429 | Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820 | ||
430 | Dual-Serial port device from MosChip Semiconductor. | ||
431 | |||
432 | The MCS7840 and MCS7820 have been developed to connect a wide range | ||
433 | of standard serial devices to a USB host. The MCS7840 has a USB | ||
434 | device controller connected to four (4) individual UARTs while the | ||
435 | MCS7820 controller connects to two (2) individual UARTs. | ||
436 | |||
437 | To compile this driver as a module, choose M here: the | ||
438 | module will be called mos7840. If unsure, choose N. | ||
439 | |||
416 | config USB_SERIAL_NAVMAN | 440 | config USB_SERIAL_NAVMAN |
417 | tristate "USB Navman GPS device" | 441 | tristate "USB Navman GPS device" |
418 | depends on USB_SERIAL | 442 | depends on USB_SERIAL |
@@ -526,5 +550,6 @@ config USB_EZUSB | |||
526 | depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT | 550 | depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT |
527 | default y | 551 | default y |
528 | 552 | ||
553 | |||
529 | endmenu | 554 | endmenu |
530 | 555 | ||
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 8efed2ce1ba3..8dce83340e31 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -11,6 +11,7 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o | |||
11 | 11 | ||
12 | usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) | 12 | usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) |
13 | 13 | ||
14 | obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o | ||
14 | obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o | 15 | obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o |
15 | obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o | 16 | obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o |
16 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o | 17 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o |
@@ -33,6 +34,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o | |||
33 | obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o | 34 | obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o |
34 | obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o | 35 | obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o |
35 | obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o | 36 | obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o |
37 | obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o | ||
36 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o | 38 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o |
37 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o | 39 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o |
38 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o | 40 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o |
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c new file mode 100644 index 000000000000..2ccd9ded52a5 --- /dev/null +++ b/drivers/usb/serial/aircable.c | |||
@@ -0,0 +1,625 @@ | |||
1 | /* | ||
2 | * AIRcable USB Bluetooth Dongle Driver. | ||
3 | * | ||
4 | * Copyright (C) 2006 Manuel Francisco Naranjo (naranjo.manuel@gmail.com) | ||
5 | * This program is free software; you can redistribute it and/or modify it under | ||
6 | * the terms of the GNU General Public License version 2 as published by the | ||
7 | * Free Software Foundation. | ||
8 | * | ||
9 | * The device works as an standard CDC device, it has 2 interfaces, the first | ||
10 | * one is for firmware access and the second is the serial one. | ||
11 | * The protocol is very simply, there are two posibilities reading or writing. | ||
12 | * When writting the first urb must have a Header that starts with 0x20 0x29 the | ||
13 | * next two bytes must say how much data will be sended. | ||
14 | * When reading the process is almost equal except that the header starts with | ||
15 | * 0x00 0x20. | ||
16 | * | ||
17 | * The device simply need some stuff to understand data comming from the usb | ||
18 | * buffer: The First and Second byte is used for a Header, the Third and Fourth | ||
19 | * tells the device the amount of information the package holds. | ||
20 | * Packages are 60 bytes long Header Stuff. | ||
21 | * When writting to the device the first two bytes of the header are 0x20 0x29 | ||
22 | * When reading the bytes are 0x00 0x20, or 0x00 0x10, there is an strange | ||
23 | * situation, when too much data arrives to the device because it sends the data | ||
24 | * but with out the header. I will use a simply hack to override this situation, | ||
25 | * if there is data coming that does not contain any header, then that is data | ||
26 | * that must go directly to the tty, as there is no documentation about if there | ||
27 | * is any other control code, I will simply check for the first | ||
28 | * one. | ||
29 | * | ||
30 | * The driver registers himself with the USB-serial core and the USB Core. I had | ||
31 | * to implement a probe function agains USB-serial, because other way, the | ||
32 | * driver was attaching himself to both interfaces. I have tryed with different | ||
33 | * configurations of usb_serial_driver with out exit, only the probe function | ||
34 | * could handle this correctly. | ||
35 | * | ||
36 | * I have taken some info from a Greg Kroah-Hartman article: | ||
37 | * http://www.linuxjournal.com/article/6573 | ||
38 | * And from Linux Device Driver Kit CD, which is a great work, the authors taken | ||
39 | * the work to recompile lots of information an knowladge in drivers development | ||
40 | * and made it all avaible inside a cd. | ||
41 | * URL: http://kernel.org/pub/linux/kernel/people/gregkh/ddk/ | ||
42 | * | ||
43 | */ | ||
44 | |||
45 | #include <linux/tty.h> | ||
46 | #include <linux/tty_flip.h> | ||
47 | #include <linux/circ_buf.h> | ||
48 | #include <linux/usb.h> | ||
49 | #include <linux/usb/serial.h> | ||
50 | |||
51 | static int debug; | ||
52 | |||
53 | /* Vendor and Product ID */ | ||
54 | #define AIRCABLE_VID 0x16CA | ||
55 | #define AIRCABLE_USB_PID 0x1502 | ||
56 | |||
57 | /* write buffer size defines */ | ||
58 | #define AIRCABLE_BUF_SIZE 2048 | ||
59 | |||
60 | /* Protocol Stuff */ | ||
61 | #define HCI_HEADER_LENGTH 0x4 | ||
62 | #define TX_HEADER_0 0x20 | ||
63 | #define TX_HEADER_1 0x29 | ||
64 | #define RX_HEADER_0 0x00 | ||
65 | #define RX_HEADER_1 0x20 | ||
66 | #define MAX_HCI_FRAMESIZE 60 | ||
67 | #define HCI_COMPLETE_FRAME 64 | ||
68 | |||
69 | /* rx_flags */ | ||
70 | #define THROTTLED 0x01 | ||
71 | #define ACTUALLY_THROTTLED 0x02 | ||
72 | |||
73 | /* | ||
74 | * Version Information | ||
75 | */ | ||
76 | #define DRIVER_VERSION "v1.0b2" | ||
77 | #define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>" | ||
78 | #define DRIVER_DESC "AIRcable USB Driver" | ||
79 | |||
80 | /* ID table that will be registered with USB core */ | ||
81 | static struct usb_device_id id_table [] = { | ||
82 | { USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) }, | ||
83 | { }, | ||
84 | }; | ||
85 | MODULE_DEVICE_TABLE(usb, id_table); | ||
86 | |||
87 | |||
88 | /* Internal Structure */ | ||
89 | struct aircable_private { | ||
90 | spinlock_t rx_lock; /* spinlock for the receive lines */ | ||
91 | struct circ_buf *tx_buf; /* write buffer */ | ||
92 | struct circ_buf *rx_buf; /* read buffer */ | ||
93 | int rx_flags; /* for throttilng */ | ||
94 | struct work_struct rx_work; /* work cue for the receiving line */ | ||
95 | }; | ||
96 | |||
97 | /* Private methods */ | ||
98 | |||
99 | /* Circular Buffer Methods, code from ti_usb_3410_5052 used */ | ||
100 | /* | ||
101 | * serial_buf_clear | ||
102 | * | ||
103 | * Clear out all data in the circular buffer. | ||
104 | */ | ||
105 | static void serial_buf_clear(struct circ_buf *cb) | ||
106 | { | ||
107 | cb->head = cb->tail = 0; | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * serial_buf_alloc | ||
112 | * | ||
113 | * Allocate a circular buffer and all associated memory. | ||
114 | */ | ||
115 | static struct circ_buf *serial_buf_alloc(void) | ||
116 | { | ||
117 | struct circ_buf *cb; | ||
118 | cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL); | ||
119 | if (cb == NULL) | ||
120 | return NULL; | ||
121 | cb->buf = kmalloc(AIRCABLE_BUF_SIZE, GFP_KERNEL); | ||
122 | if (cb->buf == NULL) { | ||
123 | kfree(cb); | ||
124 | return NULL; | ||
125 | } | ||
126 | serial_buf_clear(cb); | ||
127 | return cb; | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * serial_buf_free | ||
132 | * | ||
133 | * Free the buffer and all associated memory. | ||
134 | */ | ||
135 | static void serial_buf_free(struct circ_buf *cb) | ||
136 | { | ||
137 | kfree(cb->buf); | ||
138 | kfree(cb); | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * serial_buf_data_avail | ||
143 | * | ||
144 | * Return the number of bytes of data available in the circular | ||
145 | * buffer. | ||
146 | */ | ||
147 | static int serial_buf_data_avail(struct circ_buf *cb) | ||
148 | { | ||
149 | return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * serial_buf_put | ||
154 | * | ||
155 | * Copy data data from a user buffer and put it into the circular buffer. | ||
156 | * Restrict to the amount of space available. | ||
157 | * | ||
158 | * Return the number of bytes copied. | ||
159 | */ | ||
160 | static int serial_buf_put(struct circ_buf *cb, const char *buf, int count) | ||
161 | { | ||
162 | int c, ret = 0; | ||
163 | while (1) { | ||
164 | c = CIRC_SPACE_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE); | ||
165 | if (count < c) | ||
166 | c = count; | ||
167 | if (c <= 0) | ||
168 | break; | ||
169 | memcpy(cb->buf + cb->head, buf, c); | ||
170 | cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1); | ||
171 | buf += c; | ||
172 | count -= c; | ||
173 | ret= c; | ||
174 | } | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * serial_buf_get | ||
180 | * | ||
181 | * Get data from the circular buffer and copy to the given buffer. | ||
182 | * Restrict to the amount of data available. | ||
183 | * | ||
184 | * Return the number of bytes copied. | ||
185 | */ | ||
186 | static int serial_buf_get(struct circ_buf *cb, char *buf, int count) | ||
187 | { | ||
188 | int c, ret = 0; | ||
189 | while (1) { | ||
190 | c = CIRC_CNT_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE); | ||
191 | if (count < c) | ||
192 | c = count; | ||
193 | if (c <= 0) | ||
194 | break; | ||
195 | memcpy(buf, cb->buf + cb->tail, c); | ||
196 | cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1); | ||
197 | buf += c; | ||
198 | count -= c; | ||
199 | ret= c; | ||
200 | } | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | /* End of circula buffer methods */ | ||
205 | |||
206 | static void aircable_send(struct usb_serial_port *port) | ||
207 | { | ||
208 | int count, result; | ||
209 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
210 | unsigned char* buf; | ||
211 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
212 | if (port->write_urb_busy) | ||
213 | return; | ||
214 | |||
215 | count = min(serial_buf_data_avail(priv->tx_buf), MAX_HCI_FRAMESIZE); | ||
216 | if (count == 0) | ||
217 | return; | ||
218 | |||
219 | buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC); | ||
220 | if (!buf) { | ||
221 | err("%s- kzalloc(%d) failed.", __FUNCTION__, | ||
222 | count + HCI_HEADER_LENGTH); | ||
223 | return; | ||
224 | } | ||
225 | |||
226 | buf[0] = TX_HEADER_0; | ||
227 | buf[1] = TX_HEADER_1; | ||
228 | buf[2] = (unsigned char)count; | ||
229 | buf[3] = (unsigned char)(count >> 8); | ||
230 | serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE); | ||
231 | |||
232 | memcpy(port->write_urb->transfer_buffer, buf, | ||
233 | count + HCI_HEADER_LENGTH); | ||
234 | |||
235 | kfree(buf); | ||
236 | port->write_urb_busy = 1; | ||
237 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, | ||
238 | count + HCI_HEADER_LENGTH, | ||
239 | port->write_urb->transfer_buffer); | ||
240 | port->write_urb->transfer_buffer_length = count + HCI_HEADER_LENGTH; | ||
241 | port->write_urb->dev = port->serial->dev; | ||
242 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
243 | |||
244 | if (result) { | ||
245 | dev_err(&port->dev, | ||
246 | "%s - failed submitting write urb, error %d\n", | ||
247 | __FUNCTION__, result); | ||
248 | port->write_urb_busy = 0; | ||
249 | } | ||
250 | |||
251 | schedule_work(&port->work); | ||
252 | } | ||
253 | |||
254 | static void aircable_read(void *params) | ||
255 | { | ||
256 | struct usb_serial_port *port = params; | ||
257 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
258 | struct tty_struct *tty; | ||
259 | unsigned char *data; | ||
260 | int count; | ||
261 | if (priv->rx_flags & THROTTLED){ | ||
262 | if (priv->rx_flags & ACTUALLY_THROTTLED) | ||
263 | schedule_work(&priv->rx_work); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | /* By now I will flush data to the tty in packages of no more than | ||
268 | * 64 bytes, to ensure I do not get throttled. | ||
269 | * Ask USB mailing list for better aproach. | ||
270 | */ | ||
271 | tty = port->tty; | ||
272 | |||
273 | if (!tty) | ||
274 | schedule_work(&priv->rx_work); | ||
275 | |||
276 | count = min(64, serial_buf_data_avail(priv->rx_buf)); | ||
277 | |||
278 | if (count <= 0) | ||
279 | return; //We have finished sending everything. | ||
280 | |||
281 | tty_prepare_flip_string(tty, &data, count); | ||
282 | if (!data){ | ||
283 | err("%s- kzalloc(%d) failed.", __FUNCTION__, count); | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | serial_buf_get(priv->rx_buf, data, count); | ||
288 | |||
289 | tty_flip_buffer_push(tty); | ||
290 | |||
291 | if (serial_buf_data_avail(priv->rx_buf)) | ||
292 | schedule_work(&priv->rx_work); | ||
293 | |||
294 | return; | ||
295 | } | ||
296 | /* End of private methods */ | ||
297 | |||
298 | static int aircable_probe(struct usb_serial *serial, | ||
299 | const struct usb_device_id *id) | ||
300 | { | ||
301 | struct usb_host_interface *iface_desc = serial->interface->cur_altsetting; | ||
302 | struct usb_endpoint_descriptor *endpoint; | ||
303 | int num_bulk_out=0; | ||
304 | int i; | ||
305 | |||
306 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | ||
307 | endpoint = &iface_desc->endpoint[i].desc; | ||
308 | if (((endpoint->bEndpointAddress & 0x80) == 0x00) && | ||
309 | ((endpoint->bmAttributes & 3) == 0x02)) { | ||
310 | /* we found our bulk out endpoint */ | ||
311 | dbg("found bulk out on endpoint %d", i); | ||
312 | ++num_bulk_out; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | if (num_bulk_out == 0) { | ||
317 | dbg("Invalid interface, discarding"); | ||
318 | return -ENODEV; | ||
319 | } | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int aircable_attach (struct usb_serial *serial) | ||
325 | { | ||
326 | struct usb_serial_port *port = serial->port[0]; | ||
327 | struct aircable_private *priv; | ||
328 | |||
329 | priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL); | ||
330 | if (!priv){ | ||
331 | err("%s- kmalloc(%Zd) failed.", __FUNCTION__, | ||
332 | sizeof(struct aircable_private)); | ||
333 | return -ENOMEM; | ||
334 | } | ||
335 | |||
336 | /* Allocation of Circular Buffers */ | ||
337 | priv->tx_buf = serial_buf_alloc(); | ||
338 | if (priv->tx_buf == NULL) { | ||
339 | kfree(priv); | ||
340 | return -ENOMEM; | ||
341 | } | ||
342 | |||
343 | priv->rx_buf = serial_buf_alloc(); | ||
344 | if (priv->rx_buf == NULL) { | ||
345 | kfree(priv->tx_buf); | ||
346 | kfree(priv); | ||
347 | return -ENOMEM; | ||
348 | } | ||
349 | |||
350 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | ||
351 | INIT_WORK(&priv->rx_work, aircable_read, port); | ||
352 | |||
353 | usb_set_serial_port_data(serial->port[0], priv); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static void aircable_shutdown(struct usb_serial *serial) | ||
359 | { | ||
360 | |||
361 | struct usb_serial_port *port = serial->port[0]; | ||
362 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
363 | |||
364 | dbg("%s", __FUNCTION__); | ||
365 | |||
366 | if (priv) { | ||
367 | serial_buf_free(priv->tx_buf); | ||
368 | serial_buf_free(priv->rx_buf); | ||
369 | usb_set_serial_port_data(port, NULL); | ||
370 | kfree(priv); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | static int aircable_write_room(struct usb_serial_port *port) | ||
375 | { | ||
376 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
377 | return serial_buf_data_avail(priv->tx_buf); | ||
378 | } | ||
379 | |||
380 | static int aircable_write(struct usb_serial_port *port, | ||
381 | const unsigned char *source, int count) | ||
382 | { | ||
383 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
384 | int temp; | ||
385 | |||
386 | dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); | ||
387 | |||
388 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source); | ||
389 | |||
390 | if (!count){ | ||
391 | dbg("%s - write request of 0 bytes", __FUNCTION__); | ||
392 | return count; | ||
393 | } | ||
394 | |||
395 | temp = serial_buf_put(priv->tx_buf, source, count); | ||
396 | |||
397 | aircable_send(port); | ||
398 | |||
399 | if (count > AIRCABLE_BUF_SIZE) | ||
400 | count = AIRCABLE_BUF_SIZE; | ||
401 | |||
402 | return count; | ||
403 | |||
404 | } | ||
405 | |||
406 | static void aircable_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | ||
407 | { | ||
408 | struct usb_serial_port *port = urb->context; | ||
409 | int result; | ||
410 | |||
411 | dbg("%s - urb->status: %d", __FUNCTION__ , urb->status); | ||
412 | |||
413 | /* This has been taken from cypress_m8.c cypress_write_int_callback */ | ||
414 | switch (urb->status) { | ||
415 | case 0: | ||
416 | /* success */ | ||
417 | break; | ||
418 | case -ECONNRESET: | ||
419 | case -ENOENT: | ||
420 | case -ESHUTDOWN: | ||
421 | /* this urb is terminated, clean up */ | ||
422 | dbg("%s - urb shutting down with status: %d", | ||
423 | __FUNCTION__, urb->status); | ||
424 | port->write_urb_busy = 0; | ||
425 | return; | ||
426 | default: | ||
427 | /* error in the urb, so we have to resubmit it */ | ||
428 | dbg("%s - Overflow in write", __FUNCTION__); | ||
429 | dbg("%s - nonzero write bulk status received: %d", | ||
430 | __FUNCTION__, urb->status); | ||
431 | port->write_urb->transfer_buffer_length = 1; | ||
432 | port->write_urb->dev = port->serial->dev; | ||
433 | result = usb_submit_urb(port->write_urb, GFP_KERNEL); | ||
434 | if (result) | ||
435 | dev_err(&urb->dev->dev, | ||
436 | "%s - failed resubmitting write urb, error %d\n", | ||
437 | __FUNCTION__, result); | ||
438 | else | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | port->write_urb_busy = 0; | ||
443 | |||
444 | aircable_send(port); | ||
445 | } | ||
446 | |||
447 | static void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs) | ||
448 | { | ||
449 | struct usb_serial_port *port = urb->context; | ||
450 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
451 | struct tty_struct *tty; | ||
452 | unsigned long no_packages, remaining, package_length, i; | ||
453 | int result, shift = 0; | ||
454 | unsigned char *temp; | ||
455 | |||
456 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
457 | |||
458 | if (urb->status) { | ||
459 | dbg("%s - urb->status = %d", __FUNCTION__, urb->status); | ||
460 | if (!port->open_count) { | ||
461 | dbg("%s - port is closed, exiting.", __FUNCTION__); | ||
462 | return; | ||
463 | } | ||
464 | if (urb->status == -EPROTO) { | ||
465 | dbg("%s - caught -EPROTO, resubmitting the urb", | ||
466 | __FUNCTION__); | ||
467 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | ||
468 | usb_rcvbulkpipe(port->serial->dev, | ||
469 | port->bulk_in_endpointAddress), | ||
470 | port->read_urb->transfer_buffer, | ||
471 | port->read_urb->transfer_buffer_length, | ||
472 | aircable_read_bulk_callback, port); | ||
473 | |||
474 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
475 | if (result) | ||
476 | dev_err(&urb->dev->dev, | ||
477 | "%s - failed resubmitting read urb, error %d\n", | ||
478 | __FUNCTION__, result); | ||
479 | return; | ||
480 | } | ||
481 | dbg("%s - unable to handle the error, exiting.", __FUNCTION__); | ||
482 | return; | ||
483 | } | ||
484 | |||
485 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, | ||
486 | urb->actual_length,urb->transfer_buffer); | ||
487 | |||
488 | tty = port->tty; | ||
489 | if (tty && urb->actual_length) { | ||
490 | if (urb->actual_length <= 2) { | ||
491 | /* This is an incomplete package */ | ||
492 | serial_buf_put(priv->rx_buf, urb->transfer_buffer, | ||
493 | urb->actual_length); | ||
494 | } else { | ||
495 | temp = urb->transfer_buffer; | ||
496 | if (temp[0] == RX_HEADER_0) | ||
497 | shift = HCI_HEADER_LENGTH; | ||
498 | |||
499 | remaining = urb->actual_length; | ||
500 | no_packages = urb->actual_length / (HCI_COMPLETE_FRAME); | ||
501 | |||
502 | if (urb->actual_length % HCI_COMPLETE_FRAME != 0) | ||
503 | no_packages+=1; | ||
504 | |||
505 | for (i = 0; i < no_packages ;i++) { | ||
506 | if (remaining > (HCI_COMPLETE_FRAME)) | ||
507 | package_length = HCI_COMPLETE_FRAME; | ||
508 | else | ||
509 | package_length = remaining; | ||
510 | remaining -= package_length; | ||
511 | |||
512 | serial_buf_put(priv->rx_buf, | ||
513 | urb->transfer_buffer + shift + | ||
514 | (HCI_COMPLETE_FRAME) * (i), | ||
515 | package_length - shift); | ||
516 | } | ||
517 | } | ||
518 | aircable_read(port); | ||
519 | } | ||
520 | |||
521 | /* Schedule the next read _if_ we are still open */ | ||
522 | if (port->open_count) { | ||
523 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | ||
524 | usb_rcvbulkpipe(port->serial->dev, | ||
525 | port->bulk_in_endpointAddress), | ||
526 | port->read_urb->transfer_buffer, | ||
527 | port->read_urb->transfer_buffer_length, | ||
528 | aircable_read_bulk_callback, port); | ||
529 | |||
530 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
531 | if (result) | ||
532 | dev_err(&urb->dev->dev, | ||
533 | "%s - failed resubmitting read urb, error %d\n", | ||
534 | __FUNCTION__, result); | ||
535 | } | ||
536 | |||
537 | return; | ||
538 | } | ||
539 | |||
540 | /* Based on ftdi_sio.c throttle */ | ||
541 | static void aircable_throttle(struct usb_serial_port *port) | ||
542 | { | ||
543 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
544 | unsigned long flags; | ||
545 | |||
546 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
547 | |||
548 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
549 | priv->rx_flags |= THROTTLED; | ||
550 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
551 | } | ||
552 | |||
553 | /* Based on ftdi_sio.c unthrottle */ | ||
554 | static void aircable_unthrottle(struct usb_serial_port *port) | ||
555 | { | ||
556 | struct aircable_private *priv = usb_get_serial_port_data(port); | ||
557 | int actually_throttled; | ||
558 | unsigned long flags; | ||
559 | |||
560 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
561 | |||
562 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
563 | actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; | ||
564 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | ||
565 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
566 | |||
567 | if (actually_throttled) | ||
568 | schedule_work(&priv->rx_work); | ||
569 | } | ||
570 | |||
571 | static struct usb_serial_driver aircable_device = { | ||
572 | .description = "aircable", | ||
573 | .id_table = id_table, | ||
574 | .num_ports = 1, | ||
575 | .attach = aircable_attach, | ||
576 | .probe = aircable_probe, | ||
577 | .shutdown = aircable_shutdown, | ||
578 | .write = aircable_write, | ||
579 | .write_room = aircable_write_room, | ||
580 | .write_bulk_callback = aircable_write_bulk_callback, | ||
581 | .read_bulk_callback = aircable_read_bulk_callback, | ||
582 | .throttle = aircable_throttle, | ||
583 | .unthrottle = aircable_unthrottle, | ||
584 | }; | ||
585 | |||
586 | static struct usb_driver aircable_driver = { | ||
587 | .name = "aircable", | ||
588 | .probe = usb_serial_probe, | ||
589 | .disconnect = usb_serial_disconnect, | ||
590 | .id_table = id_table, | ||
591 | }; | ||
592 | |||
593 | static int __init aircable_init (void) | ||
594 | { | ||
595 | int retval; | ||
596 | retval = usb_serial_register(&aircable_device); | ||
597 | if (retval) | ||
598 | goto failed_serial_register; | ||
599 | retval = usb_register(&aircable_driver); | ||
600 | if (retval) | ||
601 | goto failed_usb_register; | ||
602 | return 0; | ||
603 | |||
604 | failed_serial_register: | ||
605 | usb_serial_deregister(&aircable_device); | ||
606 | failed_usb_register: | ||
607 | return retval; | ||
608 | } | ||
609 | |||
610 | static void __exit aircable_exit (void) | ||
611 | { | ||
612 | usb_deregister(&aircable_driver); | ||
613 | usb_serial_deregister(&aircable_device); | ||
614 | } | ||
615 | |||
616 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
617 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
618 | MODULE_VERSION(DRIVER_VERSION); | ||
619 | MODULE_LICENSE("GPL"); | ||
620 | |||
621 | module_init(aircable_init); | ||
622 | module_exit(aircable_exit); | ||
623 | |||
624 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
625 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 62082532a8b3..6e1a84a858d4 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * AirPrime CDMA Wireless Serial USB driver | 2 | * AirPrime CDMA Wireless Serial USB driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de> | 4 | * Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License version | 7 | * modify it under the terms of the GNU General Public License version |
@@ -11,26 +11,264 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/tty.h> | 13 | #include <linux/tty.h> |
14 | #include <linux/tty_flip.h> | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/usb.h> | 16 | #include <linux/usb.h> |
16 | #include <linux/usb/serial.h> | 17 | #include <linux/usb/serial.h> |
17 | 18 | ||
18 | static struct usb_device_id id_table [] = { | 19 | static struct usb_device_id id_table [] = { |
19 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ | 20 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ |
20 | { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ | 21 | { USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ |
21 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ | 22 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ |
23 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ | ||
22 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ | 24 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ |
23 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ | 25 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ |
26 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ | ||
24 | { }, | 27 | { }, |
25 | }; | 28 | }; |
26 | MODULE_DEVICE_TABLE(usb, id_table); | 29 | MODULE_DEVICE_TABLE(usb, id_table); |
27 | 30 | ||
31 | #define URB_TRANSFER_BUFFER_SIZE 4096 | ||
32 | #define NUM_READ_URBS 4 | ||
33 | #define NUM_WRITE_URBS 4 | ||
34 | #define NUM_BULK_EPS 3 | ||
35 | #define MAX_BULK_EPS 6 | ||
36 | |||
37 | /* if overridden by the user, then use their value for the size of the | ||
38 | * read and write urbs, and the number of endpoints */ | ||
39 | static int buffer_size = URB_TRANSFER_BUFFER_SIZE; | ||
40 | static int endpoints = NUM_BULK_EPS; | ||
41 | static int debug; | ||
42 | struct airprime_private { | ||
43 | spinlock_t lock; | ||
44 | int outstanding_urbs; | ||
45 | int throttled; | ||
46 | struct urb *read_urbp[NUM_READ_URBS]; | ||
47 | }; | ||
48 | |||
49 | static void airprime_read_bulk_callback(struct urb *urb, struct pt_regs *regs) | ||
50 | { | ||
51 | struct usb_serial_port *port = urb->context; | ||
52 | unsigned char *data = urb->transfer_buffer; | ||
53 | struct tty_struct *tty; | ||
54 | int result; | ||
55 | |||
56 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
57 | |||
58 | if (urb->status) { | ||
59 | dbg("%s - nonzero read bulk status received: %d", | ||
60 | __FUNCTION__, urb->status); | ||
61 | /* something happened, so free up the memory for this urb */ | ||
62 | if (urb->transfer_buffer) { | ||
63 | kfree (urb->transfer_buffer); | ||
64 | urb->transfer_buffer = NULL; | ||
65 | } | ||
66 | return; | ||
67 | } | ||
68 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | ||
69 | |||
70 | tty = port->tty; | ||
71 | if (tty && urb->actual_length) { | ||
72 | tty_insert_flip_string (tty, data, urb->actual_length); | ||
73 | tty_flip_buffer_push (tty); | ||
74 | } | ||
75 | |||
76 | result = usb_submit_urb (urb, GFP_ATOMIC); | ||
77 | if (result) | ||
78 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", | ||
79 | __FUNCTION__, result); | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | static void airprime_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | ||
84 | { | ||
85 | struct usb_serial_port *port = urb->context; | ||
86 | struct airprime_private *priv = usb_get_serial_port_data(port); | ||
87 | unsigned long flags; | ||
88 | |||
89 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
90 | |||
91 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
92 | kfree (urb->transfer_buffer); | ||
93 | |||
94 | if (urb->status) | ||
95 | dbg("%s - nonzero write bulk status received: %d", | ||
96 | __FUNCTION__, urb->status); | ||
97 | spin_lock_irqsave(&priv->lock, flags); | ||
98 | --priv->outstanding_urbs; | ||
99 | spin_unlock_irqrestore(&priv->lock, flags); | ||
100 | |||
101 | usb_serial_port_softint(port); | ||
102 | } | ||
103 | |||
104 | static int airprime_open(struct usb_serial_port *port, struct file *filp) | ||
105 | { | ||
106 | struct airprime_private *priv = usb_get_serial_port_data(port); | ||
107 | struct usb_serial *serial = port->serial; | ||
108 | struct urb *urb; | ||
109 | char *buffer = NULL; | ||
110 | int i; | ||
111 | int result = 0; | ||
112 | |||
113 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
114 | |||
115 | /* initialize our private data structure if it isn't already created */ | ||
116 | if (!priv) { | ||
117 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
118 | if (!priv) { | ||
119 | result = -ENOMEM; | ||
120 | goto out; | ||
121 | } | ||
122 | spin_lock_init(&priv->lock); | ||
123 | usb_set_serial_port_data(port, priv); | ||
124 | } | ||
125 | |||
126 | for (i = 0; i < NUM_READ_URBS; ++i) { | ||
127 | buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
128 | if (!buffer) { | ||
129 | dev_err(&port->dev, "%s - out of memory.\n", | ||
130 | __FUNCTION__); | ||
131 | result = -ENOMEM; | ||
132 | goto errout; | ||
133 | } | ||
134 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
135 | if (!urb) { | ||
136 | dev_err(&port->dev, "%s - no more urbs?\n", | ||
137 | __FUNCTION__); | ||
138 | result = -ENOMEM; | ||
139 | goto errout; | ||
140 | } | ||
141 | usb_fill_bulk_urb(urb, serial->dev, | ||
142 | usb_rcvbulkpipe(serial->dev, | ||
143 | port->bulk_out_endpointAddress), | ||
144 | buffer, buffer_size, | ||
145 | airprime_read_bulk_callback, port); | ||
146 | result = usb_submit_urb(urb, GFP_KERNEL); | ||
147 | if (result) { | ||
148 | dev_err(&port->dev, | ||
149 | "%s - failed submitting read urb %d for port %d, error %d\n", | ||
150 | __FUNCTION__, i, port->number, result); | ||
151 | goto errout; | ||
152 | } | ||
153 | /* remember this urb so we can kill it when the port is closed */ | ||
154 | priv->read_urbp[i] = urb; | ||
155 | } | ||
156 | goto out; | ||
157 | |||
158 | errout: | ||
159 | /* some error happened, cancel any submitted urbs and clean up anything that | ||
160 | got allocated successfully */ | ||
161 | |||
162 | for ( ; i >= 0; --i) { | ||
163 | urb = priv->read_urbp[i]; | ||
164 | if (urb) { | ||
165 | /* This urb was submitted successfully. So we have to | ||
166 | cancel it. | ||
167 | Unlinking the urb will invoke read_bulk_callback() | ||
168 | with an error status, so its transfer buffer will | ||
169 | be freed there */ | ||
170 | if (usb_unlink_urb (urb) != -EINPROGRESS) { | ||
171 | /* comments in drivers/usb/core/urb.c say this | ||
172 | can only happen if the urb was never submitted, | ||
173 | or has completed already. | ||
174 | Either way we may have to free the transfer | ||
175 | buffer here. */ | ||
176 | if (urb->transfer_buffer) { | ||
177 | kfree (urb->transfer_buffer); | ||
178 | urb->transfer_buffer = NULL; | ||
179 | } | ||
180 | } | ||
181 | usb_free_urb (urb); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | out: | ||
186 | return result; | ||
187 | } | ||
188 | |||
189 | static void airprime_close(struct usb_serial_port *port, struct file * filp) | ||
190 | { | ||
191 | struct airprime_private *priv = usb_get_serial_port_data(port); | ||
192 | int i; | ||
193 | |||
194 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
195 | |||
196 | /* killing the urb will invoke read_bulk_callback() with an error status, | ||
197 | so the transfer buffer will be freed there */ | ||
198 | for (i = 0; i < NUM_READ_URBS; ++i) { | ||
199 | usb_kill_urb (priv->read_urbp[i]); | ||
200 | usb_free_urb (priv->read_urbp[i]); | ||
201 | } | ||
202 | |||
203 | /* free up private structure */ | ||
204 | kfree (priv); | ||
205 | usb_set_serial_port_data(port, NULL); | ||
206 | } | ||
207 | |||
208 | static int airprime_write(struct usb_serial_port *port, | ||
209 | const unsigned char *buf, int count) | ||
210 | { | ||
211 | struct airprime_private *priv = usb_get_serial_port_data(port); | ||
212 | struct usb_serial *serial = port->serial; | ||
213 | struct urb *urb; | ||
214 | unsigned char *buffer; | ||
215 | unsigned long flags; | ||
216 | int status; | ||
217 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
218 | |||
219 | spin_lock_irqsave(&priv->lock, flags); | ||
220 | if (priv->outstanding_urbs > NUM_WRITE_URBS) { | ||
221 | spin_unlock_irqrestore(&priv->lock, flags); | ||
222 | dbg("%s - write limit hit\n", __FUNCTION__); | ||
223 | return 0; | ||
224 | } | ||
225 | spin_unlock_irqrestore(&priv->lock, flags); | ||
226 | buffer = kmalloc(count, GFP_ATOMIC); | ||
227 | if (!buffer) { | ||
228 | dev_err(&port->dev, "out of memory\n"); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
232 | if (!urb) { | ||
233 | dev_err(&port->dev, "no more free urbs\n"); | ||
234 | kfree (buffer); | ||
235 | return -ENOMEM; | ||
236 | } | ||
237 | memcpy (buffer, buf, count); | ||
238 | |||
239 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); | ||
240 | |||
241 | usb_fill_bulk_urb(urb, serial->dev, | ||
242 | usb_sndbulkpipe(serial->dev, | ||
243 | port->bulk_out_endpointAddress), | ||
244 | buffer, count, | ||
245 | airprime_write_bulk_callback, port); | ||
246 | |||
247 | /* send it down the pipe */ | ||
248 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
249 | if (status) { | ||
250 | dev_err(&port->dev, | ||
251 | "%s - usb_submit_urb(write bulk) failed with status = %d\n", | ||
252 | __FUNCTION__, status); | ||
253 | count = status; | ||
254 | kfree (buffer); | ||
255 | } else { | ||
256 | spin_lock_irqsave(&priv->lock, flags); | ||
257 | ++priv->outstanding_urbs; | ||
258 | spin_unlock_irqrestore(&priv->lock, flags); | ||
259 | } | ||
260 | /* we are done with this urb, so let the host driver | ||
261 | * really free it when it is finished with it */ | ||
262 | usb_free_urb (urb); | ||
263 | return count; | ||
264 | } | ||
265 | |||
28 | static struct usb_driver airprime_driver = { | 266 | static struct usb_driver airprime_driver = { |
29 | .name = "airprime", | 267 | .name = "airprime", |
30 | .probe = usb_serial_probe, | 268 | .probe = usb_serial_probe, |
31 | .disconnect = usb_serial_disconnect, | 269 | .disconnect = usb_serial_disconnect, |
32 | .id_table = id_table, | 270 | .id_table = id_table, |
33 | .no_dynamic_id = 1, | 271 | .no_dynamic_id = 1, |
34 | }; | 272 | }; |
35 | 273 | ||
36 | static struct usb_serial_driver airprime_device = { | 274 | static struct usb_serial_driver airprime_device = { |
@@ -42,13 +280,17 @@ static struct usb_serial_driver airprime_device = { | |||
42 | .num_interrupt_in = NUM_DONT_CARE, | 280 | .num_interrupt_in = NUM_DONT_CARE, |
43 | .num_bulk_in = NUM_DONT_CARE, | 281 | .num_bulk_in = NUM_DONT_CARE, |
44 | .num_bulk_out = NUM_DONT_CARE, | 282 | .num_bulk_out = NUM_DONT_CARE, |
45 | .num_ports = 1, | 283 | .open = airprime_open, |
284 | .close = airprime_close, | ||
285 | .write = airprime_write, | ||
46 | }; | 286 | }; |
47 | 287 | ||
48 | static int __init airprime_init(void) | 288 | static int __init airprime_init(void) |
49 | { | 289 | { |
50 | int retval; | 290 | int retval; |
51 | 291 | ||
292 | airprime_device.num_ports = | ||
293 | (endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS; | ||
52 | retval = usb_serial_register(&airprime_device); | 294 | retval = usb_serial_register(&airprime_device); |
53 | if (retval) | 295 | if (retval) |
54 | return retval; | 296 | return retval; |
@@ -60,6 +302,8 @@ static int __init airprime_init(void) | |||
60 | 302 | ||
61 | static void __exit airprime_exit(void) | 303 | static void __exit airprime_exit(void) |
62 | { | 304 | { |
305 | dbg("%s", __FUNCTION__); | ||
306 | |||
63 | usb_deregister(&airprime_driver); | 307 | usb_deregister(&airprime_driver); |
64 | usb_serial_deregister(&airprime_device); | 308 | usb_serial_deregister(&airprime_device); |
65 | } | 309 | } |
@@ -67,3 +311,10 @@ static void __exit airprime_exit(void) | |||
67 | module_init(airprime_init); | 311 | module_init(airprime_init); |
68 | module_exit(airprime_exit); | 312 | module_exit(airprime_exit); |
69 | MODULE_LICENSE("GPL"); | 313 | MODULE_LICENSE("GPL"); |
314 | |||
315 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
316 | MODULE_PARM_DESC(debug, "Debug enabled"); | ||
317 | module_param(buffer_size, int, 0); | ||
318 | MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)"); | ||
319 | module_param(endpoints, int, 0); | ||
320 | MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)"); | ||
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 970d9ef0a7a5..ca52f12f0e24 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c | |||
@@ -1,4 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2006 | ||
3 | * Simon Schulz (ark3116_driver <at> auctionant.de) | ||
4 | * | ||
2 | * ark3116 | 5 | * ark3116 |
3 | * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547, | 6 | * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547, |
4 | * productid=0x0232) (used in a datacable called KQ-U8A) | 7 | * productid=0x0232) (used in a datacable called KQ-U8A) |
@@ -8,8 +11,6 @@ | |||
8 | * | 11 | * |
9 | * - based on logs created by usbsnoopy | 12 | * - based on logs created by usbsnoopy |
10 | * | 13 | * |
11 | * Author : Simon Schulz [ark3116_driver<AT>auctionant.de] | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | 14 | * This program is free software; you can redistribute it and/or modify it |
14 | * under the terms of the GNU General Public License as published by the | 15 | * under the terms of the GNU General Public License as published by the |
15 | * Free Software Foundation; either version 2 of the License, or (at your | 16 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -22,6 +23,8 @@ | |||
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
23 | #include <linux/usb.h> | 24 | #include <linux/usb.h> |
24 | #include <linux/usb/serial.h> | 25 | #include <linux/usb/serial.h> |
26 | #include <linux/serial.h> | ||
27 | #include <asm/uaccess.h> | ||
25 | 28 | ||
26 | 29 | ||
27 | static int debug; | 30 | static int debug; |
@@ -43,10 +46,10 @@ static inline void ARK3116_SND(struct usb_serial *serial, int seq, | |||
43 | { | 46 | { |
44 | int result; | 47 | int result; |
45 | result = usb_control_msg(serial->dev, | 48 | result = usb_control_msg(serial->dev, |
46 | usb_sndctrlpipe(serial->dev,0), | 49 | usb_sndctrlpipe(serial->dev, 0), |
47 | request, requesttype, value, index, | 50 | request, requesttype, value, index, |
48 | NULL,0x00, 1000); | 51 | NULL, 0x00, 1000); |
49 | dbg("%03d > ok",seq); | 52 | dbg("%03d > ok", seq); |
50 | } | 53 | } |
51 | 54 | ||
52 | static inline void ARK3116_RCV(struct usb_serial *serial, int seq, | 55 | static inline void ARK3116_RCV(struct usb_serial *serial, int seq, |
@@ -56,27 +59,25 @@ static inline void ARK3116_RCV(struct usb_serial *serial, int seq, | |||
56 | { | 59 | { |
57 | int result; | 60 | int result; |
58 | result = usb_control_msg(serial->dev, | 61 | result = usb_control_msg(serial->dev, |
59 | usb_rcvctrlpipe(serial->dev,0), | 62 | usb_rcvctrlpipe(serial->dev, 0), |
60 | request, requesttype, value, index, | 63 | request, requesttype, value, index, |
61 | buf, 0x0000001, 1000); | 64 | buf, 0x0000001, 1000); |
62 | if (result) | 65 | if (result) |
63 | dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]); | 66 | dbg("%03d < %d bytes [0x%02X]", seq, result, buf[0]); |
64 | else | 67 | else |
65 | dbg("%03d < 0 bytes", seq); | 68 | dbg("%03d < 0 bytes", seq); |
66 | } | 69 | } |
67 | 70 | ||
68 | |||
69 | static inline void ARK3116_RCV_QUIET(struct usb_serial *serial, | 71 | static inline void ARK3116_RCV_QUIET(struct usb_serial *serial, |
70 | __u8 request, __u8 requesttype, | 72 | __u8 request, __u8 requesttype, |
71 | __u16 value, __u16 index, char *buf) | 73 | __u16 value, __u16 index, char *buf) |
72 | { | 74 | { |
73 | usb_control_msg(serial->dev, | 75 | usb_control_msg(serial->dev, |
74 | usb_rcvctrlpipe(serial->dev,0), | 76 | usb_rcvctrlpipe(serial->dev, 0), |
75 | request, requesttype, value, index, | 77 | request, requesttype, value, index, |
76 | buf, 0x0000001, 1000); | 78 | buf, 0x0000001, 1000); |
77 | } | 79 | } |
78 | 80 | ||
79 | |||
80 | static int ark3116_attach(struct usb_serial *serial) | 81 | static int ark3116_attach(struct usb_serial *serial) |
81 | { | 82 | { |
82 | char *buf; | 83 | char *buf; |
@@ -84,10 +85,10 @@ static int ark3116_attach(struct usb_serial *serial) | |||
84 | int i; | 85 | int i; |
85 | 86 | ||
86 | for (i = 0; i < serial->num_ports; ++i) { | 87 | for (i = 0; i < serial->num_ports; ++i) { |
87 | priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL); | 88 | priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL); |
88 | if (!priv) | 89 | if (!priv) |
89 | goto cleanup; | 90 | goto cleanup; |
90 | memset (priv, 0x00, sizeof (struct ark3116_private)); | 91 | memset(priv, 0x00, sizeof (struct ark3116_private)); |
91 | spin_lock_init(&priv->lock); | 92 | spin_lock_init(&priv->lock); |
92 | 93 | ||
93 | usb_set_serial_port_data(serial->port[i], priv); | 94 | usb_set_serial_port_data(serial->port[i], priv); |
@@ -95,63 +96,62 @@ static int ark3116_attach(struct usb_serial *serial) | |||
95 | 96 | ||
96 | buf = kmalloc(1, GFP_KERNEL); | 97 | buf = kmalloc(1, GFP_KERNEL); |
97 | if (!buf) { | 98 | if (!buf) { |
98 | dbg("error kmalloc -> out of mem ?"); | 99 | dbg("error kmalloc -> out of mem?"); |
99 | goto cleanup; | 100 | goto cleanup; |
100 | } | 101 | } |
101 | 102 | ||
102 | /* 3 */ | 103 | /* 3 */ |
103 | ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002); | 104 | ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002); |
104 | ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001); | 105 | ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001); |
105 | ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008); | 106 | ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008); |
106 | ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B); | 107 | ARK3116_SND(serial, 6, 0xFE, 0x40, 0x0000, 0x000B); |
107 | 108 | ||
108 | /* <-- seq7 */ | 109 | /* <-- seq7 */ |
109 | ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf); | 110 | ARK3116_RCV(serial, 7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); |
110 | ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003); | 111 | ARK3116_SND(serial, 8, 0xFE, 0x40, 0x0080, 0x0003); |
111 | ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000); | 112 | ARK3116_SND(serial, 9, 0xFE, 0x40, 0x001A, 0x0000); |
112 | ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001); | 113 | ARK3116_SND(serial, 10, 0xFE, 0x40, 0x0000, 0x0001); |
113 | ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003); | 114 | ARK3116_SND(serial, 11, 0xFE, 0x40, 0x0000, 0x0003); |
114 | 115 | ||
115 | /* <-- seq12 */ | 116 | /* <-- seq12 */ |
116 | ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf); | 117 | ARK3116_RCV(serial, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); |
117 | ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004); | 118 | ARK3116_SND(serial, 13, 0xFE, 0x40, 0x0000, 0x0004); |
118 | 119 | ||
119 | /* 14 */ | 120 | /* 14 */ |
120 | ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf); | 121 | ARK3116_RCV(serial, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); |
121 | ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004); | 122 | ARK3116_SND(serial, 15, 0xFE, 0x40, 0x0000, 0x0004); |
122 | 123 | ||
123 | /* 16 */ | 124 | /* 16 */ |
124 | ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf); | 125 | ARK3116_RCV(serial, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); |
125 | /* --> seq17 */ | 126 | /* --> seq17 */ |
126 | ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004); | 127 | ARK3116_SND(serial, 17, 0xFE, 0x40, 0x0001, 0x0004); |
127 | 128 | ||
128 | /* <-- seq18 */ | 129 | /* <-- seq18 */ |
129 | ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf); | 130 | ARK3116_RCV(serial, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); |
130 | 131 | ||
131 | /* --> seq19 */ | 132 | /* --> seq19 */ |
132 | ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004); | 133 | ARK3116_SND(serial, 19, 0xFE, 0x40, 0x0003, 0x0004); |
133 | |||
134 | 134 | ||
135 | /* <-- seq20 */ | 135 | /* <-- seq20 */ |
136 | /* seems like serial port status info (RTS, CTS,...) */ | 136 | /* seems like serial port status info (RTS, CTS, ...) */ |
137 | /* returns modem control line status ?! */ | 137 | /* returns modem control line status?! */ |
138 | ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf); | 138 | ARK3116_RCV(serial, 20, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); |
139 | 139 | ||
140 | /* set 9600 baud & do some init ?! */ | 140 | /* set 9600 baud & do some init?! */ |
141 | ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003); | 141 | ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); |
142 | ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000); | 142 | ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000); |
143 | ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001); | 143 | ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001); |
144 | ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003); | 144 | ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); |
145 | ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf); | 145 | ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); |
146 | ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003); | 146 | ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); |
147 | ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf); | 147 | ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); |
148 | ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003); | 148 | ARK3116_SND(serial, 154, 0xFE, 0x40, 0x0003, 0x0003); |
149 | 149 | ||
150 | kfree(buf); | 150 | kfree(buf); |
151 | return(0); | 151 | return 0; |
152 | 152 | ||
153 | cleanup: | 153 | cleanup: |
154 | for (--i; i>=0; --i) | 154 | for (--i; i >= 0; --i) |
155 | usb_set_serial_port_data(serial->port[i], NULL); | 155 | usb_set_serial_port_data(serial->port[i], NULL); |
156 | return -ENOMEM; | 156 | return -ENOMEM; |
157 | } | 157 | } |
@@ -180,7 +180,8 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
180 | spin_lock_irqsave(&priv->lock, flags); | 180 | spin_lock_irqsave(&priv->lock, flags); |
181 | if (!priv->termios_initialized) { | 181 | if (!priv->termios_initialized) { |
182 | *(port->tty->termios) = tty_std_termios; | 182 | *(port->tty->termios) = tty_std_termios; |
183 | port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 183 | port->tty->termios->c_cflag = B9600 | CS8 |
184 | | CREAD | HUPCL | CLOCAL; | ||
184 | priv->termios_initialized = 1; | 185 | priv->termios_initialized = 1; |
185 | } | 186 | } |
186 | spin_unlock_irqrestore(&priv->lock, flags); | 187 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -204,8 +205,8 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
204 | } | 205 | } |
205 | 206 | ||
206 | /* set data bit count (8/7/6/5) */ | 207 | /* set data bit count (8/7/6/5) */ |
207 | if (cflag & CSIZE){ | 208 | if (cflag & CSIZE) { |
208 | switch (cflag & CSIZE){ | 209 | switch (cflag & CSIZE) { |
209 | case CS5: | 210 | case CS5: |
210 | config |= 0x00; | 211 | config |= 0x00; |
211 | dbg("setting CS5"); | 212 | dbg("setting CS5"); |
@@ -219,7 +220,8 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
219 | dbg("setting CS7"); | 220 | dbg("setting CS7"); |
220 | break; | 221 | break; |
221 | default: | 222 | default: |
222 | err ("CSIZE was set but not CS5-CS8, using CS8!"); | 223 | err("CSIZE was set but not CS5-CS8, using CS8!"); |
224 | /* fall through */ | ||
223 | case CS8: | 225 | case CS8: |
224 | config |= 0x03; | 226 | config |= 0x03; |
225 | dbg("setting CS8"); | 227 | dbg("setting CS8"); |
@@ -227,8 +229,8 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
227 | } | 229 | } |
228 | } | 230 | } |
229 | 231 | ||
230 | /* set parity (NONE,EVEN,ODD) */ | 232 | /* set parity (NONE/EVEN/ODD) */ |
231 | if (cflag & PARENB){ | 233 | if (cflag & PARENB) { |
232 | if (cflag & PARODD) { | 234 | if (cflag & PARODD) { |
233 | config |= 0x08; | 235 | config |= 0x08; |
234 | dbg("setting parity to ODD"); | 236 | dbg("setting parity to ODD"); |
@@ -240,20 +242,19 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
240 | dbg("setting parity to NONE"); | 242 | dbg("setting parity to NONE"); |
241 | } | 243 | } |
242 | 244 | ||
243 | /* SET STOPBIT (1/2) */ | 245 | /* set stop bit (1/2) */ |
244 | if (cflag & CSTOPB) { | 246 | if (cflag & CSTOPB) { |
245 | config |= 0x04; | 247 | config |= 0x04; |
246 | dbg ("setting 2 stop bits"); | 248 | dbg("setting 2 stop bits"); |
247 | } else { | 249 | } else { |
248 | dbg ("setting 1 stop bit"); | 250 | dbg("setting 1 stop bit"); |
249 | } | 251 | } |
250 | 252 | ||
251 | 253 | /* set baudrate */ | |
252 | /* set baudrate: */ | ||
253 | baud = 0; | 254 | baud = 0; |
254 | switch (cflag & CBAUD){ | 255 | switch (cflag & CBAUD) { |
255 | case B0: | 256 | case B0: |
256 | err("can't set 0baud, using 9600 instead"); | 257 | err("can't set 0 baud, using 9600 instead"); |
257 | break; | 258 | break; |
258 | case B75: baud = 75; break; | 259 | case B75: baud = 75; break; |
259 | case B150: baud = 150; break; | 260 | case B150: baud = 150; break; |
@@ -285,38 +286,40 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
285 | */ | 286 | */ |
286 | if (baud == 460800) | 287 | if (baud == 460800) |
287 | /* strange, for 460800 the formula is wrong | 288 | /* strange, for 460800 the formula is wrong |
288 | * (dont use round(), then 9600baud is wrong) */ | 289 | * if using round() then 9600baud is wrong) */ |
289 | ark3116_baud = 7; | 290 | ark3116_baud = 7; |
290 | else | 291 | else |
291 | ark3116_baud = 3000000 / baud; | 292 | ark3116_baud = 3000000 / baud; |
292 | 293 | ||
293 | /* ? */ | 294 | /* ? */ |
294 | ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf); | 295 | ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf); |
296 | |||
295 | /* offset = buf[0]; */ | 297 | /* offset = buf[0]; */ |
296 | /* offset = 0x03; */ | 298 | /* offset = 0x03; */ |
297 | /* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */ | 299 | /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */ |
298 | |||
299 | 300 | ||
300 | /* set baudrate */ | 301 | /* set baudrate */ |
301 | dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud); | 302 | dbg("setting baudrate to %d (->reg=%d)", baud, ark3116_baud); |
302 | ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003); | 303 | ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); |
303 | ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF) ,0x0000); | 304 | ARK3116_SND(serial, 148, 0xFE, 0x40, |
304 | ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001); | 305 | (ark3116_baud & 0x00FF), 0x0000); |
305 | ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003); | 306 | ARK3116_SND(serial, 149, 0xFE, 0x40, |
307 | (ark3116_baud & 0xFF00) >> 8, 0x0001); | ||
308 | ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); | ||
306 | 309 | ||
307 | /* ? */ | 310 | /* ? */ |
308 | ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf); | 311 | ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); |
309 | ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003); | 312 | ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); |
310 | 313 | ||
311 | /* set data bit count, stop bit count & parity: */ | 314 | /* set data bit count, stop bit count & parity: */ |
312 | dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config); | 315 | dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config); |
313 | ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf); | 316 | ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); |
314 | ARK3116_SND(serial,154,0xFE,0x40,config,0x0003); | 317 | ARK3116_SND(serial, 154, 0xFE, 0x40, config, 0x0003); |
315 | 318 | ||
316 | if (cflag & CRTSCTS) | 319 | if (cflag & CRTSCTS) |
317 | dbg("CRTSCTS not supported by chipset ?!"); | 320 | dbg("CRTSCTS not supported by chipset?!"); |
318 | 321 | ||
319 | /* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */ | 322 | /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */ |
320 | 323 | ||
321 | kfree(buf); | 324 | kfree(buf); |
322 | return; | 325 | return; |
@@ -329,11 +332,11 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp) | |||
329 | char *buf; | 332 | char *buf; |
330 | int result = 0; | 333 | int result = 0; |
331 | 334 | ||
332 | dbg("%s - port %d", __FUNCTION__, port->number); | 335 | dbg("%s - port %d", __FUNCTION__, port->number); |
333 | 336 | ||
334 | buf = kmalloc(1, GFP_KERNEL); | 337 | buf = kmalloc(1, GFP_KERNEL); |
335 | if (!buf) { | 338 | if (!buf) { |
336 | dbg("error kmalloc -> out of mem ?"); | 339 | dbg("error kmalloc -> out of mem?"); |
337 | return -ENOMEM; | 340 | return -ENOMEM; |
338 | } | 341 | } |
339 | 342 | ||
@@ -342,44 +345,68 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp) | |||
342 | return result; | 345 | return result; |
343 | 346 | ||
344 | /* open */ | 347 | /* open */ |
345 | ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf); | 348 | ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf); |
346 | 349 | ||
347 | ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003); | 350 | ARK3116_SND(serial, 112, 0xFE, 0x40, 0x0082, 0x0003); |
348 | ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000); | 351 | ARK3116_SND(serial, 113, 0xFE, 0x40, 0x001A, 0x0000); |
349 | ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001); | 352 | ARK3116_SND(serial, 114, 0xFE, 0x40, 0x0000, 0x0001); |
350 | ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003); | 353 | ARK3116_SND(serial, 115, 0xFE, 0x40, 0x0002, 0x0003); |
351 | 354 | ||
352 | ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf); | 355 | ARK3116_RCV(serial, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); |
353 | ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004); | 356 | ARK3116_SND(serial, 117, 0xFE, 0x40, 0x0002, 0x0004); |
354 | 357 | ||
355 | ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf); | 358 | ARK3116_RCV(serial, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf); |
356 | ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004); | 359 | ARK3116_SND(serial, 119, 0xFE, 0x40, 0x0000, 0x0004); |
357 | 360 | ||
358 | ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf); | 361 | ARK3116_RCV(serial, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); |
359 | 362 | ||
360 | ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004); | 363 | ARK3116_SND(serial, 121, 0xFE, 0x40, 0x0001, 0x0004); |
361 | 364 | ||
362 | ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf); | 365 | ARK3116_RCV(serial, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); |
363 | 366 | ||
364 | ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004); | 367 | ARK3116_SND(serial, 123, 0xFE, 0x40, 0x0003, 0x0004); |
365 | 368 | ||
366 | /* returns different values (control lines ?!) */ | 369 | /* returns different values (control lines?!) */ |
367 | ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf); | 370 | ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); |
368 | 371 | ||
369 | /* initialise termios: */ | 372 | /* initialise termios */ |
370 | if (port->tty) | 373 | if (port->tty) |
371 | ark3116_set_termios(port, &tmp_termios); | 374 | ark3116_set_termios(port, &tmp_termios); |
372 | 375 | ||
373 | kfree(buf); | 376 | kfree(buf); |
374 | 377 | ||
375 | return result; | 378 | return result; |
376 | |||
377 | } | 379 | } |
378 | 380 | ||
379 | static int ark3116_ioctl(struct usb_serial_port *port, struct file *file, | 381 | static int ark3116_ioctl(struct usb_serial_port *port, struct file *file, |
380 | unsigned int cmd, unsigned long arg) | 382 | unsigned int cmd, unsigned long arg) |
381 | { | 383 | { |
382 | dbg("ioctl not supported yet..."); | 384 | struct serial_struct serstruct; |
385 | void __user *user_arg = (void __user *)arg; | ||
386 | |||
387 | switch (cmd) { | ||
388 | case TIOCGSERIAL: | ||
389 | /* XXX: Some of these values are probably wrong. */ | ||
390 | memset(&serstruct, 0, sizeof (serstruct)); | ||
391 | serstruct.type = PORT_16654; | ||
392 | serstruct.line = port->serial->minor; | ||
393 | serstruct.port = port->number; | ||
394 | serstruct.custom_divisor = 0; | ||
395 | serstruct.baud_base = 460800; | ||
396 | |||
397 | if (copy_to_user(user_arg, &serstruct, sizeof (serstruct))) | ||
398 | return -EFAULT; | ||
399 | |||
400 | return 0; | ||
401 | case TIOCSSERIAL: | ||
402 | if (copy_from_user(&serstruct, user_arg, sizeof (serstruct))) | ||
403 | return -EFAULT; | ||
404 | return 0; | ||
405 | default: | ||
406 | dbg("%s cmd 0x%04x not supported", __FUNCTION__, cmd); | ||
407 | break; | ||
408 | } | ||
409 | |||
383 | return -ENOIOCTLCMD; | 410 | return -ENOIOCTLCMD; |
384 | } | 411 | } |
385 | 412 | ||
@@ -389,7 +416,7 @@ static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file) | |||
389 | char *buf; | 416 | char *buf; |
390 | char temp; | 417 | char temp; |
391 | 418 | ||
392 | /* seems like serial port status info (RTS, CTS,...) is stored | 419 | /* seems like serial port status info (RTS, CTS, ...) is stored |
393 | * in reg(?) 0x0006 | 420 | * in reg(?) 0x0006 |
394 | * pcb connection point 11 = GND -> sets bit4 of response | 421 | * pcb connection point 11 = GND -> sets bit4 of response |
395 | * pcb connection point 7 = GND -> sets bit6 of response | 422 | * pcb connection point 7 = GND -> sets bit6 of response |
@@ -401,16 +428,16 @@ static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file) | |||
401 | return -ENOMEM; | 428 | return -ENOMEM; |
402 | } | 429 | } |
403 | 430 | ||
404 | /* read register: */ | 431 | /* read register */ |
405 | ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf); | 432 | ARK3116_RCV_QUIET(serial, 0xFE, 0xC0, 0x0000, 0x0006, buf); |
406 | temp = buf[0]; | 433 | temp = buf[0]; |
407 | kfree(buf); | 434 | kfree(buf); |
408 | 435 | ||
409 | /* i do not really know if bit4=CTS and bit6=DSR... was just a | 436 | /* i do not really know if bit4=CTS and bit6=DSR... just a |
410 | * quick guess !! | 437 | * quick guess! |
411 | */ | 438 | */ |
412 | return (temp & (1<<4) ? TIOCM_CTS : 0) | | 439 | return (temp & (1<<4) ? TIOCM_CTS : 0) |
413 | (temp & (1<<6) ? TIOCM_DSR : 0); | 440 | | (temp & (1<<6) ? TIOCM_DSR : 0); |
414 | } | 441 | } |
415 | 442 | ||
416 | static struct usb_driver ark3116_driver = { | 443 | static struct usb_driver ark3116_driver = { |
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index ee70fddcab60..e1173c1aee37 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -129,6 +129,9 @@ struct cypress_private { | |||
129 | int cmd_ctrl; /* always set this to 1 before issuing a command */ | 129 | int cmd_ctrl; /* always set this to 1 before issuing a command */ |
130 | struct cypress_buf *buf; /* write buffer */ | 130 | struct cypress_buf *buf; /* write buffer */ |
131 | int write_urb_in_use; /* write urb in use indicator */ | 131 | int write_urb_in_use; /* write urb in use indicator */ |
132 | int write_urb_interval; /* interval to use for write urb */ | ||
133 | int read_urb_interval; /* interval to use for read urb */ | ||
134 | int comm_is_ok; /* true if communication is (still) ok */ | ||
132 | int termios_initialized; | 135 | int termios_initialized; |
133 | __u8 line_control; /* holds dtr / rts value */ | 136 | __u8 line_control; /* holds dtr / rts value */ |
134 | __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */ | 137 | __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */ |
@@ -168,6 +171,7 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, | |||
168 | static int cypress_chars_in_buffer (struct usb_serial_port *port); | 171 | static int cypress_chars_in_buffer (struct usb_serial_port *port); |
169 | static void cypress_throttle (struct usb_serial_port *port); | 172 | static void cypress_throttle (struct usb_serial_port *port); |
170 | static void cypress_unthrottle (struct usb_serial_port *port); | 173 | static void cypress_unthrottle (struct usb_serial_port *port); |
174 | static void cypress_set_dead (struct usb_serial_port *port); | ||
171 | static void cypress_read_int_callback (struct urb *urb, struct pt_regs *regs); | 175 | static void cypress_read_int_callback (struct urb *urb, struct pt_regs *regs); |
172 | static void cypress_write_int_callback (struct urb *urb, struct pt_regs *regs); | 176 | static void cypress_write_int_callback (struct urb *urb, struct pt_regs *regs); |
173 | /* baud helper functions */ | 177 | /* baud helper functions */ |
@@ -288,6 +292,9 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m | |||
288 | 292 | ||
289 | priv = usb_get_serial_port_data(port); | 293 | priv = usb_get_serial_port_data(port); |
290 | 294 | ||
295 | if (!priv->comm_is_ok) | ||
296 | return -ENODEV; | ||
297 | |||
291 | switch(cypress_request_type) { | 298 | switch(cypress_request_type) { |
292 | case CYPRESS_SET_CONFIG: | 299 | case CYPRESS_SET_CONFIG: |
293 | 300 | ||
@@ -365,13 +372,12 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m | |||
365 | if (tries++ >= 3) | 372 | if (tries++ >= 3) |
366 | break; | 373 | break; |
367 | 374 | ||
368 | if (retval == EPIPE) | 375 | } while (retval != 8 && retval != -ENODEV); |
369 | usb_clear_halt(port->serial->dev, 0x00); | ||
370 | } while (retval != 8 && retval != ENODEV); | ||
371 | 376 | ||
372 | if (retval != 8) | 377 | if (retval != 8) { |
373 | err("%s - failed sending serial line settings - %d", __FUNCTION__, retval); | 378 | err("%s - failed sending serial line settings - %d", __FUNCTION__, retval); |
374 | else { | 379 | cypress_set_dead(port); |
380 | } else { | ||
375 | spin_lock_irqsave(&priv->lock, flags); | 381 | spin_lock_irqsave(&priv->lock, flags); |
376 | priv->baud_rate = new_baudrate; | 382 | priv->baud_rate = new_baudrate; |
377 | priv->cbr_mask = baud_mask; | 383 | priv->cbr_mask = baud_mask; |
@@ -392,12 +398,11 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m | |||
392 | if (tries++ >= 3) | 398 | if (tries++ >= 3) |
393 | break; | 399 | break; |
394 | 400 | ||
395 | if (retval == EPIPE) | 401 | } while (retval != 5 && retval != -ENODEV); |
396 | usb_clear_halt(port->serial->dev, 0x00); | ||
397 | } while (retval != 5 && retval != ENODEV); | ||
398 | 402 | ||
399 | if (retval != 5) { | 403 | if (retval != 5) { |
400 | err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval); | 404 | err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval); |
405 | cypress_set_dead(port); | ||
401 | return retval; | 406 | return retval; |
402 | } else { | 407 | } else { |
403 | spin_lock_irqsave(&priv->lock, flags); | 408 | spin_lock_irqsave(&priv->lock, flags); |
@@ -419,6 +424,24 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m | |||
419 | } /* cypress_serial_control */ | 424 | } /* cypress_serial_control */ |
420 | 425 | ||
421 | 426 | ||
427 | static void cypress_set_dead(struct usb_serial_port *port) | ||
428 | { | ||
429 | struct cypress_private *priv = usb_get_serial_port_data(port); | ||
430 | unsigned long flags; | ||
431 | |||
432 | spin_lock_irqsave(&priv->lock, flags); | ||
433 | if (!priv->comm_is_ok) { | ||
434 | spin_unlock_irqrestore(&priv->lock, flags); | ||
435 | return; | ||
436 | } | ||
437 | priv->comm_is_ok = 0; | ||
438 | spin_unlock_irqrestore(&priv->lock, flags); | ||
439 | |||
440 | err("cypress_m8 suspending failing port %d - interval might be too short", | ||
441 | port->number); | ||
442 | } | ||
443 | |||
444 | |||
422 | /* given a baud mask, it will return integer baud on success */ | 445 | /* given a baud mask, it will return integer baud on success */ |
423 | static int mask_to_rate (unsigned mask) | 446 | static int mask_to_rate (unsigned mask) |
424 | { | 447 | { |
@@ -472,13 +495,15 @@ static unsigned rate_to_mask (int rate) | |||
472 | static int generic_startup (struct usb_serial *serial) | 495 | static int generic_startup (struct usb_serial *serial) |
473 | { | 496 | { |
474 | struct cypress_private *priv; | 497 | struct cypress_private *priv; |
498 | struct usb_serial_port *port = serial->port[0]; | ||
475 | 499 | ||
476 | dbg("%s - port %d", __FUNCTION__, serial->port[0]->number); | 500 | dbg("%s - port %d", __FUNCTION__, port->number); |
477 | 501 | ||
478 | priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); | 502 | priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); |
479 | if (!priv) | 503 | if (!priv) |
480 | return -ENOMEM; | 504 | return -ENOMEM; |
481 | 505 | ||
506 | priv->comm_is_ok = !0; | ||
482 | spin_lock_init(&priv->lock); | 507 | spin_lock_init(&priv->lock); |
483 | priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); | 508 | priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); |
484 | if (priv->buf == NULL) { | 509 | if (priv->buf == NULL) { |
@@ -489,13 +514,24 @@ static int generic_startup (struct usb_serial *serial) | |||
489 | 514 | ||
490 | usb_reset_configuration (serial->dev); | 515 | usb_reset_configuration (serial->dev); |
491 | 516 | ||
492 | interval = 1; | ||
493 | priv->cmd_ctrl = 0; | 517 | priv->cmd_ctrl = 0; |
494 | priv->line_control = 0; | 518 | priv->line_control = 0; |
495 | priv->termios_initialized = 0; | 519 | priv->termios_initialized = 0; |
496 | priv->rx_flags = 0; | 520 | priv->rx_flags = 0; |
497 | priv->cbr_mask = B300; | 521 | priv->cbr_mask = B300; |
498 | usb_set_serial_port_data(serial->port[0], priv); | 522 | if (interval > 0) { |
523 | priv->write_urb_interval = interval; | ||
524 | priv->read_urb_interval = interval; | ||
525 | dbg("%s - port %d read & write intervals forced to %d", | ||
526 | __FUNCTION__,port->number,interval); | ||
527 | } else { | ||
528 | priv->write_urb_interval = port->interrupt_out_urb->interval; | ||
529 | priv->read_urb_interval = port->interrupt_in_urb->interval; | ||
530 | dbg("%s - port %d intervals: read=%d write=%d", | ||
531 | __FUNCTION__,port->number, | ||
532 | priv->read_urb_interval,priv->write_urb_interval); | ||
533 | } | ||
534 | usb_set_serial_port_data(port, priv); | ||
499 | 535 | ||
500 | return 0; | 536 | return 0; |
501 | } | 537 | } |
@@ -585,6 +621,9 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp) | |||
585 | 621 | ||
586 | dbg("%s - port %d", __FUNCTION__, port->number); | 622 | dbg("%s - port %d", __FUNCTION__, port->number); |
587 | 623 | ||
624 | if (!priv->comm_is_ok) | ||
625 | return -EIO; | ||
626 | |||
588 | /* clear halts before open */ | 627 | /* clear halts before open */ |
589 | usb_clear_halt(serial->dev, 0x81); | 628 | usb_clear_halt(serial->dev, 0x81); |
590 | usb_clear_halt(serial->dev, 0x02); | 629 | usb_clear_halt(serial->dev, 0x02); |
@@ -624,11 +663,12 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp) | |||
624 | usb_fill_int_urb(port->interrupt_in_urb, serial->dev, | 663 | usb_fill_int_urb(port->interrupt_in_urb, serial->dev, |
625 | usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), | 664 | usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), |
626 | port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, | 665 | port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, |
627 | cypress_read_int_callback, port, interval); | 666 | cypress_read_int_callback, port, priv->read_urb_interval); |
628 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 667 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
629 | 668 | ||
630 | if (result){ | 669 | if (result){ |
631 | dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); | 670 | dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); |
671 | cypress_set_dead(port); | ||
632 | } | 672 | } |
633 | 673 | ||
634 | return result; | 674 | return result; |
@@ -733,6 +773,9 @@ static void cypress_send(struct usb_serial_port *port) | |||
733 | struct cypress_private *priv = usb_get_serial_port_data(port); | 773 | struct cypress_private *priv = usb_get_serial_port_data(port); |
734 | unsigned long flags; | 774 | unsigned long flags; |
735 | 775 | ||
776 | if (!priv->comm_is_ok) | ||
777 | return; | ||
778 | |||
736 | dbg("%s - port %d", __FUNCTION__, port->number); | 779 | dbg("%s - port %d", __FUNCTION__, port->number); |
737 | dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size); | 780 | dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size); |
738 | 781 | ||
@@ -806,14 +849,16 @@ send: | |||
806 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size, | 849 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size, |
807 | port->interrupt_out_urb->transfer_buffer); | 850 | port->interrupt_out_urb->transfer_buffer); |
808 | 851 | ||
809 | port->interrupt_out_urb->transfer_buffer_length = actual_size; | 852 | usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev, |
810 | port->interrupt_out_urb->dev = port->serial->dev; | 853 | usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), |
811 | port->interrupt_out_urb->interval = interval; | 854 | port->interrupt_out_buffer, port->interrupt_out_size, |
855 | cypress_write_int_callback, port, priv->write_urb_interval); | ||
812 | result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC); | 856 | result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC); |
813 | if (result) { | 857 | if (result) { |
814 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, | 858 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, |
815 | result); | 859 | result); |
816 | priv->write_urb_in_use = 0; | 860 | priv->write_urb_in_use = 0; |
861 | cypress_set_dead(port); | ||
817 | } | 862 | } |
818 | 863 | ||
819 | spin_lock_irqsave(&priv->lock, flags); | 864 | spin_lock_irqsave(&priv->lock, flags); |
@@ -1214,13 +1259,18 @@ static void cypress_unthrottle (struct usb_serial_port *port) | |||
1214 | priv->rx_flags = 0; | 1259 | priv->rx_flags = 0; |
1215 | spin_unlock_irqrestore(&priv->lock, flags); | 1260 | spin_unlock_irqrestore(&priv->lock, flags); |
1216 | 1261 | ||
1262 | if (!priv->comm_is_ok) | ||
1263 | return; | ||
1264 | |||
1217 | if (actually_throttled) { | 1265 | if (actually_throttled) { |
1218 | port->interrupt_in_urb->dev = port->serial->dev; | 1266 | port->interrupt_in_urb->dev = port->serial->dev; |
1219 | 1267 | ||
1220 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | 1268 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); |
1221 | if (result) | 1269 | if (result) { |
1222 | dev_err(&port->dev, "%s - failed submitting read urb, " | 1270 | dev_err(&port->dev, "%s - failed submitting read urb, " |
1223 | "error %d\n", __FUNCTION__, result); | 1271 | "error %d\n", __FUNCTION__, result); |
1272 | cypress_set_dead(port); | ||
1273 | } | ||
1224 | } | 1274 | } |
1225 | } | 1275 | } |
1226 | 1276 | ||
@@ -1240,9 +1290,22 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
1240 | 1290 | ||
1241 | dbg("%s - port %d", __FUNCTION__, port->number); | 1291 | dbg("%s - port %d", __FUNCTION__, port->number); |
1242 | 1292 | ||
1243 | if (urb->status) { | 1293 | switch (urb->status) { |
1244 | dbg("%s - nonzero read status received: %d", __FUNCTION__, | 1294 | case 0: /* success */ |
1245 | urb->status); | 1295 | break; |
1296 | case -ECONNRESET: | ||
1297 | case -ENOENT: | ||
1298 | case -ESHUTDOWN: | ||
1299 | /* precursor to disconnect so just go away */ | ||
1300 | return; | ||
1301 | case -EPIPE: | ||
1302 | usb_clear_halt(port->serial->dev,0x81); | ||
1303 | break; | ||
1304 | default: | ||
1305 | /* something ugly is going on... */ | ||
1306 | dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n", | ||
1307 | __FUNCTION__,urb->status); | ||
1308 | cypress_set_dead(port); | ||
1246 | return; | 1309 | return; |
1247 | } | 1310 | } |
1248 | 1311 | ||
@@ -1343,18 +1406,20 @@ continue_read: | |||
1343 | 1406 | ||
1344 | /* Continue trying to always read... unless the port has closed. */ | 1407 | /* Continue trying to always read... unless the port has closed. */ |
1345 | 1408 | ||
1346 | if (port->open_count > 0) { | 1409 | if (port->open_count > 0 && priv->comm_is_ok) { |
1347 | usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, | 1410 | usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, |
1348 | usb_rcvintpipe(port->serial->dev, | 1411 | usb_rcvintpipe(port->serial->dev, |
1349 | port->interrupt_in_endpointAddress), | 1412 | port->interrupt_in_endpointAddress), |
1350 | port->interrupt_in_urb->transfer_buffer, | 1413 | port->interrupt_in_urb->transfer_buffer, |
1351 | port->interrupt_in_urb->transfer_buffer_length, | 1414 | port->interrupt_in_urb->transfer_buffer_length, |
1352 | cypress_read_int_callback, port, interval); | 1415 | cypress_read_int_callback, port, priv->read_urb_interval); |
1353 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | 1416 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); |
1354 | if (result) | 1417 | if (result) { |
1355 | dev_err(&urb->dev->dev, "%s - failed resubmitting " | 1418 | dev_err(&urb->dev->dev, "%s - failed resubmitting " |
1356 | "read urb, error %d\n", __FUNCTION__, | 1419 | "read urb, error %d\n", __FUNCTION__, |
1357 | result); | 1420 | result); |
1421 | cypress_set_dead(port); | ||
1422 | } | ||
1358 | } | 1423 | } |
1359 | 1424 | ||
1360 | return; | 1425 | return; |
@@ -1380,20 +1445,26 @@ static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs) | |||
1380 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 1445 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); |
1381 | priv->write_urb_in_use = 0; | 1446 | priv->write_urb_in_use = 0; |
1382 | return; | 1447 | return; |
1383 | case -EPIPE: /* no break needed */ | 1448 | case -EPIPE: /* no break needed; clear halt and resubmit */ |
1449 | if (!priv->comm_is_ok) | ||
1450 | break; | ||
1384 | usb_clear_halt(port->serial->dev, 0x02); | 1451 | usb_clear_halt(port->serial->dev, 0x02); |
1385 | default: | ||
1386 | /* error in the urb, so we have to resubmit it */ | 1452 | /* error in the urb, so we have to resubmit it */ |
1387 | dbg("%s - Overflow in write", __FUNCTION__); | ||
1388 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 1453 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
1389 | port->interrupt_out_urb->transfer_buffer_length = 1; | 1454 | port->interrupt_out_urb->transfer_buffer_length = 1; |
1390 | port->interrupt_out_urb->dev = port->serial->dev; | 1455 | port->interrupt_out_urb->dev = port->serial->dev; |
1391 | result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); | 1456 | result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); |
1392 | if (result) | 1457 | if (!result) |
1393 | dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", | ||
1394 | __FUNCTION__, result); | ||
1395 | else | ||
1396 | return; | 1458 | return; |
1459 | dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", | ||
1460 | __FUNCTION__, result); | ||
1461 | cypress_set_dead(port); | ||
1462 | break; | ||
1463 | default: | ||
1464 | dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n", | ||
1465 | __FUNCTION__,urb->status); | ||
1466 | cypress_set_dead(port); | ||
1467 | break; | ||
1397 | } | 1468 | } |
1398 | 1469 | ||
1399 | priv->write_urb_in_use = 0; | 1470 | priv->write_urb_in_use = 0; |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c6115aa1b445..1f7b72553f37 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1101,25 +1101,29 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att | |||
1101 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); | 1101 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); |
1102 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); | 1102 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); |
1103 | 1103 | ||
1104 | static void create_sysfs_attrs(struct usb_serial *serial) | 1104 | static int create_sysfs_attrs(struct usb_serial *serial) |
1105 | { | 1105 | { |
1106 | struct ftdi_private *priv; | 1106 | struct ftdi_private *priv; |
1107 | struct usb_device *udev; | 1107 | struct usb_device *udev; |
1108 | int retval = 0; | ||
1108 | 1109 | ||
1109 | dbg("%s",__FUNCTION__); | 1110 | dbg("%s",__FUNCTION__); |
1110 | 1111 | ||
1111 | priv = usb_get_serial_port_data(serial->port[0]); | 1112 | priv = usb_get_serial_port_data(serial->port[0]); |
1112 | udev = serial->dev; | 1113 | udev = serial->dev; |
1113 | 1114 | ||
1114 | /* XXX I've no idea if the original SIO supports the event_char | 1115 | /* XXX I've no idea if the original SIO supports the event_char |
1115 | * sysfs parameter, so I'm playing it safe. */ | 1116 | * sysfs parameter, so I'm playing it safe. */ |
1116 | if (priv->chip_type != SIO) { | 1117 | if (priv->chip_type != SIO) { |
1117 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | 1118 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); |
1118 | device_create_file(&udev->dev, &dev_attr_event_char); | 1119 | retval = device_create_file(&udev->dev, &dev_attr_event_char); |
1119 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { | 1120 | if ((!retval) && |
1120 | device_create_file(&udev->dev, &dev_attr_latency_timer); | 1121 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { |
1122 | retval = device_create_file(&udev->dev, | ||
1123 | &dev_attr_latency_timer); | ||
1121 | } | 1124 | } |
1122 | } | 1125 | } |
1126 | return retval; | ||
1123 | } | 1127 | } |
1124 | 1128 | ||
1125 | static void remove_sysfs_attrs(struct usb_serial *serial) | 1129 | static void remove_sysfs_attrs(struct usb_serial *serial) |
@@ -1162,7 +1166,8 @@ static int ftdi_sio_attach (struct usb_serial *serial) | |||
1162 | struct usb_serial_port *port = serial->port[0]; | 1166 | struct usb_serial_port *port = serial->port[0]; |
1163 | struct ftdi_private *priv; | 1167 | struct ftdi_private *priv; |
1164 | struct ftdi_sio_quirk *quirk; | 1168 | struct ftdi_sio_quirk *quirk; |
1165 | 1169 | int retval; | |
1170 | |||
1166 | dbg("%s",__FUNCTION__); | 1171 | dbg("%s",__FUNCTION__); |
1167 | 1172 | ||
1168 | priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); | 1173 | priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); |
@@ -1203,15 +1208,18 @@ static int ftdi_sio_attach (struct usb_serial *serial) | |||
1203 | usb_set_serial_port_data(serial->port[0], priv); | 1208 | usb_set_serial_port_data(serial->port[0], priv); |
1204 | 1209 | ||
1205 | ftdi_determine_type (serial->port[0]); | 1210 | ftdi_determine_type (serial->port[0]); |
1206 | create_sysfs_attrs(serial); | 1211 | retval = create_sysfs_attrs(serial); |
1212 | if (retval) | ||
1213 | dev_err(&serial->dev->dev, "Error creating sysfs files, " | ||
1214 | "continuing\n"); | ||
1207 | 1215 | ||
1208 | /* Check for device requiring special set up. */ | 1216 | /* Check for device requiring special set up. */ |
1209 | quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); | 1217 | quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); |
1210 | if (quirk && quirk->setup) { | 1218 | if (quirk && quirk->setup) { |
1211 | quirk->setup(serial); | 1219 | quirk->setup(serial); |
1212 | } | 1220 | } |
1213 | 1221 | ||
1214 | return (0); | 1222 | return 0; |
1215 | } /* ftdi_sio_attach */ | 1223 | } /* ftdi_sio_attach */ |
1216 | 1224 | ||
1217 | 1225 | ||
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 727852634be9..4b1196a8b09e 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Garmin GPS driver | 2 | * Garmin GPS driver |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Hermann Kneissel herkne@users.sourceforge.net | 4 | * Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net |
5 | * | 5 | * |
6 | * The latest version of the driver can be found at | 6 | * The latest version of the driver can be found at |
7 | * http://sourceforge.net/projects/garmin-gps/ | 7 | * http://sourceforge.net/projects/garmin-gps/ |
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
38 | #include <linux/usb/serial.h> | 38 | #include <linux/usb/serial.h> |
39 | 39 | ||
40 | #include <linux/version.h> | ||
41 | |||
40 | /* the mode to be set when the port ist opened */ | 42 | /* the mode to be set when the port ist opened */ |
41 | static int initial_mode = 1; | 43 | static int initial_mode = 1; |
42 | 44 | ||
@@ -50,7 +52,7 @@ static int debug = 0; | |||
50 | */ | 52 | */ |
51 | 53 | ||
52 | #define VERSION_MAJOR 0 | 54 | #define VERSION_MAJOR 0 |
53 | #define VERSION_MINOR 23 | 55 | #define VERSION_MINOR 28 |
54 | 56 | ||
55 | #define _STR(s) #s | 57 | #define _STR(s) #s |
56 | #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b) | 58 | #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b) |
@@ -164,7 +166,8 @@ struct garmin_data { | |||
164 | #define FLAGS_SESSION_REPLY1_SEEN 0x0080 | 166 | #define FLAGS_SESSION_REPLY1_SEEN 0x0080 |
165 | #define FLAGS_SESSION_REPLY2_SEEN 0x0040 | 167 | #define FLAGS_SESSION_REPLY2_SEEN 0x0040 |
166 | #define FLAGS_BULK_IN_ACTIVE 0x0020 | 168 | #define FLAGS_BULK_IN_ACTIVE 0x0020 |
167 | #define FLAGS_THROTTLED 0x0010 | 169 | #define FLAGS_BULK_IN_RESTART 0x0010 |
170 | #define FLAGS_THROTTLED 0x0008 | ||
168 | #define CLEAR_HALT_REQUIRED 0x0001 | 171 | #define CLEAR_HALT_REQUIRED 0x0001 |
169 | 172 | ||
170 | #define FLAGS_QUEUING 0x0100 | 173 | #define FLAGS_QUEUING 0x0100 |
@@ -224,7 +227,7 @@ static struct usb_driver garmin_driver = { | |||
224 | .probe = usb_serial_probe, | 227 | .probe = usb_serial_probe, |
225 | .disconnect = usb_serial_disconnect, | 228 | .disconnect = usb_serial_disconnect, |
226 | .id_table = id_table, | 229 | .id_table = id_table, |
227 | .no_dynamic_id = 1, | 230 | .no_dynamic_id = 1, |
228 | }; | 231 | }; |
229 | 232 | ||
230 | 233 | ||
@@ -270,7 +273,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf) | |||
270 | 273 | ||
271 | 274 | ||
272 | static void send_to_tty(struct usb_serial_port *port, | 275 | static void send_to_tty(struct usb_serial_port *port, |
273 | char *data, unsigned int actual_length) | 276 | char *data, unsigned int actual_length) |
274 | { | 277 | { |
275 | struct tty_struct *tty = port->tty; | 278 | struct tty_struct *tty = port->tty; |
276 | 279 | ||
@@ -294,15 +297,15 @@ static void send_to_tty(struct usb_serial_port *port, | |||
294 | * queue a received (usb-)packet for later processing | 297 | * queue a received (usb-)packet for later processing |
295 | */ | 298 | */ |
296 | static int pkt_add(struct garmin_data * garmin_data_p, | 299 | static int pkt_add(struct garmin_data * garmin_data_p, |
297 | unsigned char *data, unsigned int data_length) | 300 | unsigned char *data, unsigned int data_length) |
298 | { | 301 | { |
302 | int state = 0; | ||
299 | int result = 0; | 303 | int result = 0; |
300 | unsigned long flags; | 304 | unsigned long flags; |
301 | struct garmin_packet *pkt; | 305 | struct garmin_packet *pkt; |
302 | 306 | ||
303 | /* process only packets containg data ... */ | 307 | /* process only packets containg data ... */ |
304 | if (data_length) { | 308 | if (data_length) { |
305 | garmin_data_p->flags |= FLAGS_QUEUING; | ||
306 | pkt = kmalloc(sizeof(struct garmin_packet)+data_length, | 309 | pkt = kmalloc(sizeof(struct garmin_packet)+data_length, |
307 | GFP_ATOMIC); | 310 | GFP_ATOMIC); |
308 | if (pkt == NULL) { | 311 | if (pkt == NULL) { |
@@ -313,14 +316,16 @@ static int pkt_add(struct garmin_data * garmin_data_p, | |||
313 | memcpy(pkt->data, data, data_length); | 316 | memcpy(pkt->data, data, data_length); |
314 | 317 | ||
315 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 318 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
319 | garmin_data_p->flags |= FLAGS_QUEUING; | ||
316 | result = list_empty(&garmin_data_p->pktlist); | 320 | result = list_empty(&garmin_data_p->pktlist); |
317 | pkt->seq = garmin_data_p->seq_counter++; | 321 | pkt->seq = garmin_data_p->seq_counter++; |
318 | list_add_tail(&pkt->list, &garmin_data_p->pktlist); | 322 | list_add_tail(&pkt->list, &garmin_data_p->pktlist); |
323 | state = garmin_data_p->state; | ||
319 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 324 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
320 | 325 | ||
321 | /* in serial mode, if someone is waiting for data from | 326 | /* in serial mode, if someone is waiting for data from |
322 | the device, iconvert and send the next packet to tty. */ | 327 | the device, iconvert and send the next packet to tty. */ |
323 | if (result && (garmin_data_p->state == STATE_GSP_WAIT_DATA)) { | 328 | if (result && (state == STATE_GSP_WAIT_DATA)) { |
324 | gsp_next_packet(garmin_data_p); | 329 | gsp_next_packet(garmin_data_p); |
325 | } | 330 | } |
326 | } | 331 | } |
@@ -370,9 +375,9 @@ static void pkt_clear(struct garmin_data * garmin_data_p) | |||
370 | static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) | 375 | static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) |
371 | { | 376 | { |
372 | __u8 pkt[10]; | 377 | __u8 pkt[10]; |
373 | __u8 cksum = 0; | 378 | __u8 cksum = 0; |
374 | __u8 *ptr = pkt; | 379 | __u8 *ptr = pkt; |
375 | unsigned l = 0; | 380 | unsigned l = 0; |
376 | 381 | ||
377 | dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id); | 382 | dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id); |
378 | 383 | ||
@@ -416,7 +421,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id) | |||
416 | static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) | 421 | static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) |
417 | { | 422 | { |
418 | const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; | 423 | const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; |
419 | __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; | 424 | __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; |
420 | 425 | ||
421 | int cksum = 0; | 426 | int cksum = 0; |
422 | int n = 0; | 427 | int n = 0; |
@@ -447,11 +452,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) | |||
447 | n++; | 452 | n++; |
448 | } | 453 | } |
449 | 454 | ||
450 | if ((0xff & (cksum + *recpkt)) != 0) { | 455 | if ((0xff & (cksum + *recpkt)) != 0) { |
451 | dbg("%s - invalid checksum, expected %02x, got %02x", | 456 | dbg("%s - invalid checksum, expected %02x, got %02x", |
452 | __FUNCTION__, 0xff & -cksum, 0xff & *recpkt); | 457 | __FUNCTION__, 0xff & -cksum, 0xff & *recpkt); |
453 | return -EINVPKT; | 458 | return -EINVPKT; |
454 | } | 459 | } |
455 | 460 | ||
456 | usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL); | 461 | usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL); |
457 | usbdata[1] = __cpu_to_le32(pktid); | 462 | usbdata[1] = __cpu_to_le32(pktid); |
@@ -491,20 +496,28 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count) | |||
491 | */ | 496 | */ |
492 | 497 | ||
493 | static int gsp_receive(struct garmin_data * garmin_data_p, | 498 | static int gsp_receive(struct garmin_data * garmin_data_p, |
494 | const unsigned char *buf, int count) | 499 | const unsigned char *buf, int count) |
495 | { | 500 | { |
501 | unsigned long flags; | ||
496 | int offs = 0; | 502 | int offs = 0; |
497 | int ack_or_nak_seen = 0; | 503 | int ack_or_nak_seen = 0; |
498 | int i = 0; | 504 | int i = 0; |
499 | __u8 *dest = garmin_data_p->inbuffer; | 505 | __u8 *dest; |
500 | int size = garmin_data_p->insize; | 506 | int size; |
501 | // dleSeen: set if last byte read was a DLE | 507 | // dleSeen: set if last byte read was a DLE |
502 | int dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN; | 508 | int dleSeen; |
503 | // skip: if set, skip incoming data until possible start of | 509 | // skip: if set, skip incoming data until possible start of |
504 | // new packet | 510 | // new packet |
505 | int skip = garmin_data_p->flags & FLAGS_GSP_SKIP; | 511 | int skip; |
506 | __u8 data; | 512 | __u8 data; |
507 | 513 | ||
514 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
515 | dest = garmin_data_p->inbuffer; | ||
516 | size = garmin_data_p->insize; | ||
517 | dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN; | ||
518 | skip = garmin_data_p->flags & FLAGS_GSP_SKIP; | ||
519 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
520 | |||
508 | dbg("%s - dle=%d skip=%d size=%d count=%d", | 521 | dbg("%s - dle=%d skip=%d size=%d count=%d", |
509 | __FUNCTION__, dleSeen, skip, size, count); | 522 | __FUNCTION__, dleSeen, skip, size, count); |
510 | 523 | ||
@@ -572,6 +585,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p, | |||
572 | } | 585 | } |
573 | } | 586 | } |
574 | 587 | ||
588 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
589 | |||
575 | garmin_data_p->insize = size; | 590 | garmin_data_p->insize = size; |
576 | 591 | ||
577 | // copy flags back to structure | 592 | // copy flags back to structure |
@@ -587,6 +602,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p, | |||
587 | 602 | ||
588 | if (ack_or_nak_seen) { | 603 | if (ack_or_nak_seen) { |
589 | garmin_data_p->state = STATE_GSP_WAIT_DATA; | 604 | garmin_data_p->state = STATE_GSP_WAIT_DATA; |
605 | } | ||
606 | |||
607 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
608 | |||
609 | if (ack_or_nak_seen) { | ||
590 | gsp_next_packet(garmin_data_p); | 610 | gsp_next_packet(garmin_data_p); |
591 | } | 611 | } |
592 | 612 | ||
@@ -676,7 +696,7 @@ static int gsp_send(struct garmin_data * garmin_data_p, | |||
676 | src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH; | 696 | src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH; |
677 | if (k > (GARMIN_PKTHDR_LENGTH-2)) { | 697 | if (k > (GARMIN_PKTHDR_LENGTH-2)) { |
678 | /* can't add stuffing DLEs in place, move data to end | 698 | /* can't add stuffing DLEs in place, move data to end |
679 | of buffer ... */ | 699 | of buffer ... */ |
680 | dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen; | 700 | dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen; |
681 | memcpy(dst, src, datalen); | 701 | memcpy(dst, src, datalen); |
682 | src = dst; | 702 | src = dst; |
@@ -755,8 +775,9 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p) | |||
755 | * or even incomplete packets | 775 | * or even incomplete packets |
756 | */ | 776 | */ |
757 | static int nat_receive(struct garmin_data * garmin_data_p, | 777 | static int nat_receive(struct garmin_data * garmin_data_p, |
758 | const unsigned char *buf, int count) | 778 | const unsigned char *buf, int count) |
759 | { | 779 | { |
780 | unsigned long flags; | ||
760 | __u8 * dest; | 781 | __u8 * dest; |
761 | int offs = 0; | 782 | int offs = 0; |
762 | int result = count; | 783 | int result = count; |
@@ -803,7 +824,9 @@ static int nat_receive(struct garmin_data * garmin_data_p, | |||
803 | /* if this was an abort-transfer command, | 824 | /* if this was an abort-transfer command, |
804 | flush all queued data. */ | 825 | flush all queued data. */ |
805 | if (isAbortTrfCmnd(garmin_data_p->inbuffer)) { | 826 | if (isAbortTrfCmnd(garmin_data_p->inbuffer)) { |
827 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
806 | garmin_data_p->flags |= FLAGS_DROP_DATA; | 828 | garmin_data_p->flags |= FLAGS_DROP_DATA; |
829 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
807 | pkt_clear(garmin_data_p); | 830 | pkt_clear(garmin_data_p); |
808 | } | 831 | } |
809 | } | 832 | } |
@@ -839,12 +862,15 @@ static void priv_status_resp(struct usb_serial_port *port) | |||
839 | 862 | ||
840 | static int process_resetdev_request(struct usb_serial_port *port) | 863 | static int process_resetdev_request(struct usb_serial_port *port) |
841 | { | 864 | { |
865 | unsigned long flags; | ||
842 | int status; | 866 | int status; |
843 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 867 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
844 | 868 | ||
869 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
845 | garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED); | 870 | garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED); |
846 | garmin_data_p->state = STATE_RESET; | 871 | garmin_data_p->state = STATE_RESET; |
847 | garmin_data_p->serial_num = 0; | 872 | garmin_data_p->serial_num = 0; |
873 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
848 | 874 | ||
849 | usb_kill_urb (port->interrupt_in_urb); | 875 | usb_kill_urb (port->interrupt_in_urb); |
850 | dbg("%s - usb_reset_device", __FUNCTION__ ); | 876 | dbg("%s - usb_reset_device", __FUNCTION__ ); |
@@ -862,6 +888,7 @@ static int process_resetdev_request(struct usb_serial_port *port) | |||
862 | */ | 888 | */ |
863 | static int garmin_clear(struct garmin_data * garmin_data_p) | 889 | static int garmin_clear(struct garmin_data * garmin_data_p) |
864 | { | 890 | { |
891 | unsigned long flags; | ||
865 | int status = 0; | 892 | int status = 0; |
866 | 893 | ||
867 | struct usb_serial_port *port = garmin_data_p->port; | 894 | struct usb_serial_port *port = garmin_data_p->port; |
@@ -875,8 +902,10 @@ static int garmin_clear(struct garmin_data * garmin_data_p) | |||
875 | /* flush all queued data */ | 902 | /* flush all queued data */ |
876 | pkt_clear(garmin_data_p); | 903 | pkt_clear(garmin_data_p); |
877 | 904 | ||
905 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
878 | garmin_data_p->insize = 0; | 906 | garmin_data_p->insize = 0; |
879 | garmin_data_p->outsize = 0; | 907 | garmin_data_p->outsize = 0; |
908 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
880 | 909 | ||
881 | return status; | 910 | return status; |
882 | } | 911 | } |
@@ -888,6 +917,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p) | |||
888 | 917 | ||
889 | static int garmin_init_session(struct usb_serial_port *port) | 918 | static int garmin_init_session(struct usb_serial_port *port) |
890 | { | 919 | { |
920 | unsigned long flags; | ||
891 | struct usb_serial *serial = port->serial; | 921 | struct usb_serial *serial = port->serial; |
892 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 922 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
893 | int status = 0; | 923 | int status = 0; |
@@ -913,7 +943,9 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
913 | 943 | ||
914 | if (status >= 0) { | 944 | if (status >= 0) { |
915 | 945 | ||
946 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
916 | garmin_data_p->ignorePkts++; | 947 | garmin_data_p->ignorePkts++; |
948 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
917 | 949 | ||
918 | /* not needed, but the win32 driver does it too ... */ | 950 | /* not needed, but the win32 driver does it too ... */ |
919 | status = garmin_write_bulk(port, | 951 | status = garmin_write_bulk(port, |
@@ -921,7 +953,9 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
921 | sizeof(GARMIN_START_SESSION_REQ2)); | 953 | sizeof(GARMIN_START_SESSION_REQ2)); |
922 | if (status >= 0) { | 954 | if (status >= 0) { |
923 | status = 0; | 955 | status = 0; |
956 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
924 | garmin_data_p->ignorePkts++; | 957 | garmin_data_p->ignorePkts++; |
958 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
925 | } | 959 | } |
926 | } | 960 | } |
927 | } | 961 | } |
@@ -935,6 +969,7 @@ static int garmin_init_session(struct usb_serial_port *port) | |||
935 | 969 | ||
936 | static int garmin_open (struct usb_serial_port *port, struct file *filp) | 970 | static int garmin_open (struct usb_serial_port *port, struct file *filp) |
937 | { | 971 | { |
972 | unsigned long flags; | ||
938 | int status = 0; | 973 | int status = 0; |
939 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 974 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
940 | 975 | ||
@@ -948,9 +983,11 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp) | |||
948 | if (port->tty) | 983 | if (port->tty) |
949 | port->tty->low_latency = 1; | 984 | port->tty->low_latency = 1; |
950 | 985 | ||
986 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
951 | garmin_data_p->mode = initial_mode; | 987 | garmin_data_p->mode = initial_mode; |
952 | garmin_data_p->count = 0; | 988 | garmin_data_p->count = 0; |
953 | garmin_data_p->flags = 0; | 989 | garmin_data_p->flags = 0; |
990 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
954 | 991 | ||
955 | /* shutdown any bulk reads that might be going on */ | 992 | /* shutdown any bulk reads that might be going on */ |
956 | usb_kill_urb (port->write_urb); | 993 | usb_kill_urb (port->write_urb); |
@@ -996,6 +1033,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp) | |||
996 | 1033 | ||
997 | static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | 1034 | static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) |
998 | { | 1035 | { |
1036 | unsigned long flags; | ||
999 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1037 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1000 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1038 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1001 | 1039 | ||
@@ -1007,7 +1045,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1007 | if (urb->status) { | 1045 | if (urb->status) { |
1008 | dbg("%s - nonzero write bulk status received: %d", | 1046 | dbg("%s - nonzero write bulk status received: %d", |
1009 | __FUNCTION__, urb->status); | 1047 | __FUNCTION__, urb->status); |
1048 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1010 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; | 1049 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; |
1050 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1011 | } | 1051 | } |
1012 | 1052 | ||
1013 | usb_serial_port_softint(port); | 1053 | usb_serial_port_softint(port); |
@@ -1015,8 +1055,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1015 | 1055 | ||
1016 | 1056 | ||
1017 | static int garmin_write_bulk (struct usb_serial_port *port, | 1057 | static int garmin_write_bulk (struct usb_serial_port *port, |
1018 | const unsigned char *buf, int count) | 1058 | const unsigned char *buf, int count) |
1019 | { | 1059 | { |
1060 | unsigned long flags; | ||
1020 | struct usb_serial *serial = port->serial; | 1061 | struct usb_serial *serial = port->serial; |
1021 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1062 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1022 | struct urb *urb; | 1063 | struct urb *urb; |
@@ -1026,7 +1067,9 @@ static int garmin_write_bulk (struct usb_serial_port *port, | |||
1026 | dbg("%s - port %d, state %d", __FUNCTION__, port->number, | 1067 | dbg("%s - port %d, state %d", __FUNCTION__, port->number, |
1027 | garmin_data_p->state); | 1068 | garmin_data_p->state); |
1028 | 1069 | ||
1070 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1029 | garmin_data_p->flags &= ~FLAGS_DROP_DATA; | 1071 | garmin_data_p->flags &= ~FLAGS_DROP_DATA; |
1072 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1030 | 1073 | ||
1031 | buffer = kmalloc (count, GFP_ATOMIC); | 1074 | buffer = kmalloc (count, GFP_ATOMIC); |
1032 | if (!buffer) { | 1075 | if (!buffer) { |
@@ -1053,7 +1096,9 @@ static int garmin_write_bulk (struct usb_serial_port *port, | |||
1053 | urb->transfer_flags |= URB_ZERO_PACKET; | 1096 | urb->transfer_flags |= URB_ZERO_PACKET; |
1054 | 1097 | ||
1055 | if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { | 1098 | if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { |
1099 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1056 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; | 1100 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; |
1101 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1057 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | 1102 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { |
1058 | pkt_clear(garmin_data_p); | 1103 | pkt_clear(garmin_data_p); |
1059 | garmin_data_p->state = STATE_GSP_WAIT_DATA; | 1104 | garmin_data_p->state = STATE_GSP_WAIT_DATA; |
@@ -1087,8 +1132,9 @@ static int garmin_write_bulk (struct usb_serial_port *port, | |||
1087 | 1132 | ||
1088 | 1133 | ||
1089 | static int garmin_write (struct usb_serial_port *port, | 1134 | static int garmin_write (struct usb_serial_port *port, |
1090 | const unsigned char *buf, int count) | 1135 | const unsigned char *buf, int count) |
1091 | { | 1136 | { |
1137 | unsigned long flags; | ||
1092 | int pktid, pktsiz, len; | 1138 | int pktid, pktsiz, len; |
1093 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1139 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1094 | __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; | 1140 | __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; |
@@ -1139,7 +1185,9 @@ static int garmin_write (struct usb_serial_port *port, | |||
1139 | break; | 1185 | break; |
1140 | 1186 | ||
1141 | case PRIV_PKTID_RESET_REQ: | 1187 | case PRIV_PKTID_RESET_REQ: |
1188 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1142 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; | 1189 | garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; |
1190 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1143 | break; | 1191 | break; |
1144 | 1192 | ||
1145 | case PRIV_PKTID_SET_DEF_MODE: | 1193 | case PRIV_PKTID_SET_DEF_MODE: |
@@ -1155,6 +1203,8 @@ static int garmin_write (struct usb_serial_port *port, | |||
1155 | } | 1203 | } |
1156 | } | 1204 | } |
1157 | 1205 | ||
1206 | garmin_data_p->ignorePkts = 0; | ||
1207 | |||
1158 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { | 1208 | if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { |
1159 | return gsp_receive(garmin_data_p, buf, count); | 1209 | return gsp_receive(garmin_data_p, buf, count); |
1160 | } else { /* MODE_NATIVE */ | 1210 | } else { /* MODE_NATIVE */ |
@@ -1177,10 +1227,10 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port) | |||
1177 | { | 1227 | { |
1178 | /* | 1228 | /* |
1179 | * Report back the number of bytes currently in our input buffer. | 1229 | * Report back the number of bytes currently in our input buffer. |
1180 | * Will this lock up the driver - the buffer contains an incomplete | 1230 | * Will this lock up the driver - the buffer contains an incomplete |
1181 | * package which will not be written to the device until it | 1231 | * package which will not be written to the device until it |
1182 | * has been completed ? | 1232 | * has been completed ? |
1183 | */ | 1233 | */ |
1184 | //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1234 | //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1185 | //return garmin_data_p->insize; | 1235 | //return garmin_data_p->insize; |
1186 | return 0; | 1236 | return 0; |
@@ -1190,6 +1240,8 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port) | |||
1190 | static void garmin_read_process(struct garmin_data * garmin_data_p, | 1240 | static void garmin_read_process(struct garmin_data * garmin_data_p, |
1191 | unsigned char *data, unsigned data_length) | 1241 | unsigned char *data, unsigned data_length) |
1192 | { | 1242 | { |
1243 | unsigned long flags; | ||
1244 | |||
1193 | if (garmin_data_p->flags & FLAGS_DROP_DATA) { | 1245 | if (garmin_data_p->flags & FLAGS_DROP_DATA) { |
1194 | /* abort-transfer cmd is actice */ | 1246 | /* abort-transfer cmd is actice */ |
1195 | dbg("%s - pkt dropped", __FUNCTION__); | 1247 | dbg("%s - pkt dropped", __FUNCTION__); |
@@ -1200,11 +1252,14 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, | |||
1200 | if a reset is required or not when closing | 1252 | if a reset is required or not when closing |
1201 | the device */ | 1253 | the device */ |
1202 | if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, | 1254 | if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, |
1203 | sizeof(GARMIN_APP_LAYER_REPLY))) | 1255 | sizeof(GARMIN_APP_LAYER_REPLY))) { |
1256 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1204 | garmin_data_p->flags |= FLAGS_APP_RESP_SEEN; | 1257 | garmin_data_p->flags |= FLAGS_APP_RESP_SEEN; |
1258 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1259 | } | ||
1205 | 1260 | ||
1206 | /* if throttling is active or postprecessing is required | 1261 | /* if throttling is active or postprecessing is required |
1207 | put the received data in th input queue, otherwise | 1262 | put the received data in the input queue, otherwise |
1208 | send it directly to the tty port */ | 1263 | send it directly to the tty port */ |
1209 | if (garmin_data_p->flags & FLAGS_QUEUING) { | 1264 | if (garmin_data_p->flags & FLAGS_QUEUING) { |
1210 | pkt_add(garmin_data_p, data, data_length); | 1265 | pkt_add(garmin_data_p, data, data_length); |
@@ -1221,6 +1276,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p, | |||
1221 | 1276 | ||
1222 | static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | 1277 | static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) |
1223 | { | 1278 | { |
1279 | unsigned long flags; | ||
1224 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1280 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1225 | struct usb_serial *serial = port->serial; | 1281 | struct usb_serial *serial = port->serial; |
1226 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1282 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
@@ -1245,19 +1301,30 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1245 | 1301 | ||
1246 | garmin_read_process(garmin_data_p, data, urb->actual_length); | 1302 | garmin_read_process(garmin_data_p, data, urb->actual_length); |
1247 | 1303 | ||
1248 | /* Continue trying to read until nothing more is received */ | 1304 | if (urb->actual_length == 0 && |
1249 | if (urb->actual_length > 0) { | 1305 | 0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) { |
1250 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 1306 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
1251 | usb_rcvbulkpipe (serial->dev, | 1307 | garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART; |
1252 | port->bulk_in_endpointAddress), | 1308 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
1253 | port->read_urb->transfer_buffer, | ||
1254 | port->read_urb->transfer_buffer_length, | ||
1255 | garmin_read_bulk_callback, port); | ||
1256 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 1309 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
1257 | if (status) | 1310 | if (status) |
1258 | dev_err(&port->dev, | 1311 | dev_err(&port->dev, |
1259 | "%s - failed resubmitting read urb, error %d\n", | 1312 | "%s - failed resubmitting read urb, error %d\n", |
1260 | __FUNCTION__, status); | 1313 | __FUNCTION__, status); |
1314 | } else if (urb->actual_length > 0) { | ||
1315 | /* Continue trying to read until nothing more is received */ | ||
1316 | if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) { | ||
1317 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
1318 | if (status) | ||
1319 | dev_err(&port->dev, | ||
1320 | "%s - failed resubmitting read urb, error %d\n", | ||
1321 | __FUNCTION__, status); | ||
1322 | } | ||
1323 | } else { | ||
1324 | dbg("%s - end of bulk data", __FUNCTION__); | ||
1325 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1326 | garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE; | ||
1327 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1261 | } | 1328 | } |
1262 | return; | 1329 | return; |
1263 | } | 1330 | } |
@@ -1265,6 +1332,7 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1265 | 1332 | ||
1266 | static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | 1333 | static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) |
1267 | { | 1334 | { |
1335 | unsigned long flags; | ||
1268 | int status; | 1336 | int status; |
1269 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1337 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1270 | struct usb_serial *serial = port->serial; | 1338 | struct usb_serial *serial = port->serial; |
@@ -1297,25 +1365,41 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | |||
1297 | 1365 | ||
1298 | dbg("%s - bulk data available.", __FUNCTION__); | 1366 | dbg("%s - bulk data available.", __FUNCTION__); |
1299 | 1367 | ||
1300 | /* bulk data available */ | 1368 | if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { |
1301 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 1369 | |
1302 | usb_rcvbulkpipe (serial->dev, | 1370 | /* bulk data available */ |
1303 | port->bulk_in_endpointAddress), | 1371 | usb_fill_bulk_urb (port->read_urb, serial->dev, |
1304 | port->read_urb->transfer_buffer, | 1372 | usb_rcvbulkpipe (serial->dev, |
1305 | port->read_urb->transfer_buffer_length, | 1373 | port->bulk_in_endpointAddress), |
1306 | garmin_read_bulk_callback, port); | 1374 | port->read_urb->transfer_buffer, |
1307 | status = usb_submit_urb(port->read_urb, GFP_KERNEL); | 1375 | port->read_urb->transfer_buffer_length, |
1308 | if (status) { | 1376 | garmin_read_bulk_callback, port); |
1309 | dev_err(&port->dev, | 1377 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
1310 | "%s - failed submitting read urb, error %d\n", | 1378 | if (status) { |
1311 | __FUNCTION__, status); | 1379 | dev_err(&port->dev, |
1380 | "%s - failed submitting read urb, error %d\n", | ||
1381 | __FUNCTION__, status); | ||
1382 | } else { | ||
1383 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1384 | garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE; | ||
1385 | /* do not send this packet to the user */ | ||
1386 | garmin_data_p->ignorePkts = 1; | ||
1387 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1388 | } | ||
1389 | } else { | ||
1390 | /* bulk-in transfer still active */ | ||
1391 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1392 | garmin_data_p->flags |= FLAGS_BULK_IN_RESTART; | ||
1393 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1312 | } | 1394 | } |
1313 | 1395 | ||
1314 | } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY)) | 1396 | } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY)) |
1315 | && 0 == memcmp(data, GARMIN_START_SESSION_REPLY, | 1397 | && 0 == memcmp(data, GARMIN_START_SESSION_REPLY, |
1316 | sizeof(GARMIN_START_SESSION_REPLY))) { | 1398 | sizeof(GARMIN_START_SESSION_REPLY))) { |
1317 | 1399 | ||
1400 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1318 | garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN; | 1401 | garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN; |
1402 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1319 | 1403 | ||
1320 | /* save the serial number */ | 1404 | /* save the serial number */ |
1321 | garmin_data_p->serial_num | 1405 | garmin_data_p->serial_num |
@@ -1330,7 +1414,9 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | |||
1330 | ignore it. */ | 1414 | ignore it. */ |
1331 | dbg("%s - pkt ignored (%d)", | 1415 | dbg("%s - pkt ignored (%d)", |
1332 | __FUNCTION__, garmin_data_p->ignorePkts); | 1416 | __FUNCTION__, garmin_data_p->ignorePkts); |
1417 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1333 | garmin_data_p->ignorePkts--; | 1418 | garmin_data_p->ignorePkts--; |
1419 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1334 | } else { | 1420 | } else { |
1335 | garmin_read_process(garmin_data_p, data, urb->actual_length); | 1421 | garmin_read_process(garmin_data_p, data, urb->actual_length); |
1336 | } | 1422 | } |
@@ -1351,18 +1437,20 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs) | |||
1351 | */ | 1437 | */ |
1352 | static int garmin_flush_queue(struct garmin_data * garmin_data_p) | 1438 | static int garmin_flush_queue(struct garmin_data * garmin_data_p) |
1353 | { | 1439 | { |
1440 | unsigned long flags; | ||
1354 | struct garmin_packet *pkt; | 1441 | struct garmin_packet *pkt; |
1355 | 1442 | ||
1356 | if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) { | 1443 | if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) { |
1357 | pkt = pkt_pop(garmin_data_p); | 1444 | pkt = pkt_pop(garmin_data_p); |
1358 | if (pkt != NULL) { | 1445 | if (pkt != NULL) { |
1359 | |||
1360 | send_to_tty(garmin_data_p->port, pkt->data, pkt->size); | 1446 | send_to_tty(garmin_data_p->port, pkt->data, pkt->size); |
1361 | kfree(pkt); | 1447 | kfree(pkt); |
1362 | mod_timer(&garmin_data_p->timer, (1)+jiffies); | 1448 | mod_timer(&garmin_data_p->timer, (1)+jiffies); |
1363 | 1449 | ||
1364 | } else { | 1450 | } else { |
1451 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1365 | garmin_data_p->flags &= ~FLAGS_QUEUING; | 1452 | garmin_data_p->flags &= ~FLAGS_QUEUING; |
1453 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1366 | } | 1454 | } |
1367 | } | 1455 | } |
1368 | return 0; | 1456 | return 0; |
@@ -1371,26 +1459,41 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p) | |||
1371 | 1459 | ||
1372 | static void garmin_throttle (struct usb_serial_port *port) | 1460 | static void garmin_throttle (struct usb_serial_port *port) |
1373 | { | 1461 | { |
1462 | unsigned long flags; | ||
1374 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1463 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1375 | 1464 | ||
1376 | dbg("%s - port %d", __FUNCTION__, port->number); | 1465 | dbg("%s - port %d", __FUNCTION__, port->number); |
1377 | /* set flag, data received will be put into a queue | 1466 | /* set flag, data received will be put into a queue |
1378 | for later processing */ | 1467 | for later processing */ |
1468 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1379 | garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED; | 1469 | garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED; |
1470 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1380 | } | 1471 | } |
1381 | 1472 | ||
1382 | 1473 | ||
1383 | static void garmin_unthrottle (struct usb_serial_port *port) | 1474 | static void garmin_unthrottle (struct usb_serial_port *port) |
1384 | { | 1475 | { |
1476 | unsigned long flags; | ||
1385 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1477 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1478 | int status; | ||
1386 | 1479 | ||
1387 | dbg("%s - port %d", __FUNCTION__, port->number); | 1480 | dbg("%s - port %d", __FUNCTION__, port->number); |
1481 | spin_lock_irqsave(&garmin_data_p->lock, flags); | ||
1388 | garmin_data_p->flags &= ~FLAGS_THROTTLED; | 1482 | garmin_data_p->flags &= ~FLAGS_THROTTLED; |
1483 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | ||
1389 | 1484 | ||
1390 | /* in native mode send queued data to tty, in | 1485 | /* in native mode send queued data to tty, in |
1391 | serial mode nothing needs to be done here */ | 1486 | serial mode nothing needs to be done here */ |
1392 | if (garmin_data_p->mode == MODE_NATIVE) | 1487 | if (garmin_data_p->mode == MODE_NATIVE) |
1393 | garmin_flush_queue(garmin_data_p); | 1488 | garmin_flush_queue(garmin_data_p); |
1489 | |||
1490 | if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { | ||
1491 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
1492 | if (status) | ||
1493 | dev_err(&port->dev, | ||
1494 | "%s - failed resubmitting read urb, error %d\n", | ||
1495 | __FUNCTION__, status); | ||
1496 | } | ||
1394 | } | 1497 | } |
1395 | 1498 | ||
1396 | 1499 | ||
@@ -1420,11 +1523,12 @@ static int garmin_attach (struct usb_serial *serial) | |||
1420 | 1523 | ||
1421 | dbg("%s", __FUNCTION__); | 1524 | dbg("%s", __FUNCTION__); |
1422 | 1525 | ||
1423 | garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); | 1526 | garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL); |
1424 | if (garmin_data_p == NULL) { | 1527 | if (garmin_data_p == NULL) { |
1425 | dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); | 1528 | dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); |
1426 | return -ENOMEM; | 1529 | return -ENOMEM; |
1427 | } | 1530 | } |
1531 | memset (garmin_data_p, 0, sizeof(struct garmin_data)); | ||
1428 | init_timer(&garmin_data_p->timer); | 1532 | init_timer(&garmin_data_p->timer); |
1429 | spin_lock_init(&garmin_data_p->lock); | 1533 | spin_lock_init(&garmin_data_p->lock); |
1430 | INIT_LIST_HEAD(&garmin_data_p->pktlist); | 1534 | INIT_LIST_HEAD(&garmin_data_p->pktlist); |
@@ -1459,10 +1563,10 @@ static void garmin_shutdown (struct usb_serial *serial) | |||
1459 | /* All of the device info needed */ | 1563 | /* All of the device info needed */ |
1460 | static struct usb_serial_driver garmin_device = { | 1564 | static struct usb_serial_driver garmin_device = { |
1461 | .driver = { | 1565 | .driver = { |
1462 | .owner = THIS_MODULE, | 1566 | .owner = THIS_MODULE, |
1463 | .name = "garmin_gps", | 1567 | .name = "garmin_gps", |
1464 | }, | 1568 | }, |
1465 | .description = "Garmin GPS usb/tty", | 1569 | .description = "Garmin GPS usb/tty", |
1466 | .id_table = id_table, | 1570 | .id_table = id_table, |
1467 | .num_interrupt_in = 1, | 1571 | .num_interrupt_in = 1, |
1468 | .num_bulk_in = 1, | 1572 | .num_bulk_in = 1, |
@@ -1483,6 +1587,7 @@ static struct usb_serial_driver garmin_device = { | |||
1483 | }; | 1587 | }; |
1484 | 1588 | ||
1485 | 1589 | ||
1590 | |||
1486 | static int __init garmin_init (void) | 1591 | static int __init garmin_init (void) |
1487 | { | 1592 | { |
1488 | int retval; | 1593 | int retval; |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 9840bade79f9..bfc6998cd16f 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -652,11 +652,6 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) | |||
652 | port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE; | 652 | port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE; |
653 | 653 | ||
654 | msleep(1000*initial_wait); | 654 | msleep(1000*initial_wait); |
655 | /* Start reading from the device */ | ||
656 | usb_fill_bulk_urb(port->read_urb, serial->dev, | ||
657 | usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), | ||
658 | port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, | ||
659 | ipaq_read_bulk_callback, port); | ||
660 | 655 | ||
661 | /* | 656 | /* |
662 | * Send out control message observed in win98 sniffs. Not sure what | 657 | * Send out control message observed in win98 sniffs. Not sure what |
@@ -670,18 +665,31 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) | |||
670 | result = usb_control_msg(serial->dev, | 665 | result = usb_control_msg(serial->dev, |
671 | usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21, | 666 | usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21, |
672 | 0x1, 0, NULL, 0, 100); | 667 | 0x1, 0, NULL, 0, 100); |
673 | if (result == 0) { | 668 | if (!result) |
674 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | 669 | break; |
675 | if (result) { | 670 | |
676 | err("%s - failed submitting read urb, error %d", __FUNCTION__, result); | ||
677 | goto error; | ||
678 | } | ||
679 | return 0; | ||
680 | } | ||
681 | msleep(1000); | 671 | msleep(1000); |
682 | } | 672 | } |
683 | err("%s - failed doing control urb, error %d", __FUNCTION__, result); | 673 | |
684 | goto error; | 674 | if (!retries && result) { |
675 | err("%s - failed doing control urb, error %d", __FUNCTION__, | ||
676 | result); | ||
677 | goto error; | ||
678 | } | ||
679 | |||
680 | /* Start reading from the device */ | ||
681 | usb_fill_bulk_urb(port->read_urb, serial->dev, | ||
682 | usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), | ||
683 | port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, | ||
684 | ipaq_read_bulk_callback, port); | ||
685 | |||
686 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
687 | if (result) { | ||
688 | err("%s - failed submitting read urb, error %d", __FUNCTION__, result); | ||
689 | goto error; | ||
690 | } | ||
691 | |||
692 | return 0; | ||
685 | 693 | ||
686 | enomem: | 694 | enomem: |
687 | result = -ENOMEM; | 695 | result = -ENOMEM; |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c new file mode 100644 index 000000000000..95bf57166c59 --- /dev/null +++ b/drivers/usb/serial/mos7840.c | |||
@@ -0,0 +1,2962 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
15 | * | ||
16 | * Clean ups from Moschip version and a few ioctl implementations by: | ||
17 | * Paul B Schroeder <pschroeder "at" uplogix "dot" com> | ||
18 | * | ||
19 | * Originally based on drivers/usb/serial/io_edgeport.c which is: | ||
20 | * Copyright (C) 2000 Inside Out Networks, All rights reserved. | ||
21 | * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/tty.h> | ||
30 | #include <linux/tty_driver.h> | ||
31 | #include <linux/tty_flip.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/serial.h> | ||
34 | #include <linux/usb.h> | ||
35 | #include <linux/usb/serial.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | |||
38 | /* | ||
39 | * Version Information | ||
40 | */ | ||
41 | #define DRIVER_VERSION "1.3.1" | ||
42 | #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver" | ||
43 | |||
44 | /* | ||
45 | * 16C50 UART register defines | ||
46 | */ | ||
47 | |||
48 | #define LCR_BITS_5 0x00 /* 5 bits/char */ | ||
49 | #define LCR_BITS_6 0x01 /* 6 bits/char */ | ||
50 | #define LCR_BITS_7 0x02 /* 7 bits/char */ | ||
51 | #define LCR_BITS_8 0x03 /* 8 bits/char */ | ||
52 | #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ | ||
53 | |||
54 | #define LCR_STOP_1 0x00 /* 1 stop bit */ | ||
55 | #define LCR_STOP_1_5 0x04 /* 1.5 stop bits (if 5 bits/char) */ | ||
56 | #define LCR_STOP_2 0x04 /* 2 stop bits (if 6-8 bits/char) */ | ||
57 | #define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ | ||
58 | |||
59 | #define LCR_PAR_NONE 0x00 /* No parity */ | ||
60 | #define LCR_PAR_ODD 0x08 /* Odd parity */ | ||
61 | #define LCR_PAR_EVEN 0x18 /* Even parity */ | ||
62 | #define LCR_PAR_MARK 0x28 /* Force parity bit to 1 */ | ||
63 | #define LCR_PAR_SPACE 0x38 /* Force parity bit to 0 */ | ||
64 | #define LCR_PAR_MASK 0x38 /* Mask for parity field */ | ||
65 | |||
66 | #define LCR_SET_BREAK 0x40 /* Set Break condition */ | ||
67 | #define LCR_DL_ENABLE 0x80 /* Enable access to divisor latch */ | ||
68 | |||
69 | #define MCR_DTR 0x01 /* Assert DTR */ | ||
70 | #define MCR_RTS 0x02 /* Assert RTS */ | ||
71 | #define MCR_OUT1 0x04 /* Loopback only: Sets state of RI */ | ||
72 | #define MCR_MASTER_IE 0x08 /* Enable interrupt outputs */ | ||
73 | #define MCR_LOOPBACK 0x10 /* Set internal (digital) loopback mode */ | ||
74 | #define MCR_XON_ANY 0x20 /* Enable any char to exit XOFF mode */ | ||
75 | |||
76 | #define MOS7840_MSR_CTS 0x10 /* Current state of CTS */ | ||
77 | #define MOS7840_MSR_DSR 0x20 /* Current state of DSR */ | ||
78 | #define MOS7840_MSR_RI 0x40 /* Current state of RI */ | ||
79 | #define MOS7840_MSR_CD 0x80 /* Current state of CD */ | ||
80 | |||
81 | /* | ||
82 | * Defines used for sending commands to port | ||
83 | */ | ||
84 | |||
85 | #define WAIT_FOR_EVER (HZ * 0 ) /* timeout urb is wait for ever */ | ||
86 | #define MOS_WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ | ||
87 | |||
88 | #define MOS_PORT1 0x0200 | ||
89 | #define MOS_PORT2 0x0300 | ||
90 | #define MOS_VENREG 0x0000 | ||
91 | #define MOS_MAX_PORT 0x02 | ||
92 | #define MOS_WRITE 0x0E | ||
93 | #define MOS_READ 0x0D | ||
94 | |||
95 | /* Requests */ | ||
96 | #define MCS_RD_RTYPE 0xC0 | ||
97 | #define MCS_WR_RTYPE 0x40 | ||
98 | #define MCS_RDREQ 0x0D | ||
99 | #define MCS_WRREQ 0x0E | ||
100 | #define MCS_CTRL_TIMEOUT 500 | ||
101 | #define VENDOR_READ_LENGTH (0x01) | ||
102 | |||
103 | #define MAX_NAME_LEN 64 | ||
104 | |||
105 | #define ZLP_REG1 0x3A //Zero_Flag_Reg1 58 | ||
106 | #define ZLP_REG5 0x3E //Zero_Flag_Reg5 62 | ||
107 | |||
108 | /* For higher baud Rates use TIOCEXBAUD */ | ||
109 | #define TIOCEXBAUD 0x5462 | ||
110 | |||
111 | /* vendor id and device id defines */ | ||
112 | |||
113 | #define USB_VENDOR_ID_MOSCHIP 0x9710 | ||
114 | #define MOSCHIP_DEVICE_ID_7840 0x7840 | ||
115 | #define MOSCHIP_DEVICE_ID_7820 0x7820 | ||
116 | |||
117 | /* Interrupt Rotinue Defines */ | ||
118 | |||
119 | #define SERIAL_IIR_RLS 0x06 | ||
120 | #define SERIAL_IIR_MS 0x00 | ||
121 | |||
122 | /* | ||
123 | * Emulation of the bit mask on the LINE STATUS REGISTER. | ||
124 | */ | ||
125 | #define SERIAL_LSR_DR 0x0001 | ||
126 | #define SERIAL_LSR_OE 0x0002 | ||
127 | #define SERIAL_LSR_PE 0x0004 | ||
128 | #define SERIAL_LSR_FE 0x0008 | ||
129 | #define SERIAL_LSR_BI 0x0010 | ||
130 | |||
131 | #define MOS_MSR_DELTA_CTS 0x10 | ||
132 | #define MOS_MSR_DELTA_DSR 0x20 | ||
133 | #define MOS_MSR_DELTA_RI 0x40 | ||
134 | #define MOS_MSR_DELTA_CD 0x80 | ||
135 | |||
136 | // Serial Port register Address | ||
137 | #define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01)) | ||
138 | #define FIFO_CONTROL_REGISTER ((__u16)(0x02)) | ||
139 | #define LINE_CONTROL_REGISTER ((__u16)(0x03)) | ||
140 | #define MODEM_CONTROL_REGISTER ((__u16)(0x04)) | ||
141 | #define LINE_STATUS_REGISTER ((__u16)(0x05)) | ||
142 | #define MODEM_STATUS_REGISTER ((__u16)(0x06)) | ||
143 | #define SCRATCH_PAD_REGISTER ((__u16)(0x07)) | ||
144 | #define DIVISOR_LATCH_LSB ((__u16)(0x00)) | ||
145 | #define DIVISOR_LATCH_MSB ((__u16)(0x01)) | ||
146 | |||
147 | #define CLK_MULTI_REGISTER ((__u16)(0x02)) | ||
148 | #define CLK_START_VALUE_REGISTER ((__u16)(0x03)) | ||
149 | |||
150 | #define SERIAL_LCR_DLAB ((__u16)(0x0080)) | ||
151 | |||
152 | /* | ||
153 | * URB POOL related defines | ||
154 | */ | ||
155 | #define NUM_URBS 16 /* URB Count */ | ||
156 | #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ | ||
157 | |||
158 | |||
159 | static struct usb_device_id moschip_port_id_table[] = { | ||
160 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | ||
161 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, | ||
162 | {} /* terminating entry */ | ||
163 | }; | ||
164 | |||
165 | static __devinitdata struct usb_device_id moschip_id_table_combined[] = { | ||
166 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | ||
167 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, | ||
168 | {} /* terminating entry */ | ||
169 | }; | ||
170 | |||
171 | MODULE_DEVICE_TABLE(usb, moschip_id_table_combined); | ||
172 | |||
173 | /* This structure holds all of the local port information */ | ||
174 | |||
175 | struct moschip_port { | ||
176 | int port_num; /*Actual port number in the device(1,2,etc) */ | ||
177 | struct urb *write_urb; /* write URB for this port */ | ||
178 | struct urb *read_urb; /* read URB for this port */ | ||
179 | __u8 shadowLCR; /* last LCR value received */ | ||
180 | __u8 shadowMCR; /* last MCR value received */ | ||
181 | char open; | ||
182 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ | ||
183 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ | ||
184 | int delta_msr_cond; | ||
185 | struct async_icount icount; | ||
186 | struct usb_serial_port *port; /* loop back to the owner of this object */ | ||
187 | |||
188 | /*Offsets */ | ||
189 | __u8 SpRegOffset; | ||
190 | __u8 ControlRegOffset; | ||
191 | __u8 DcrRegOffset; | ||
192 | //for processing control URBS in interrupt context | ||
193 | struct urb *control_urb; | ||
194 | char *ctrl_buf; | ||
195 | int MsrLsr; | ||
196 | |||
197 | struct urb *write_urb_pool[NUM_URBS]; | ||
198 | }; | ||
199 | |||
200 | |||
201 | static int debug; | ||
202 | static int mos7840_num_ports; //this says the number of ports in the device | ||
203 | static int mos7840_num_open_ports; | ||
204 | |||
205 | |||
206 | /* | ||
207 | * mos7840_set_reg_sync | ||
208 | * To set the Control register by calling usb_fill_control_urb function | ||
209 | * by passing usb_sndctrlpipe function as parameter. | ||
210 | */ | ||
211 | |||
212 | static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg, | ||
213 | __u16 val) | ||
214 | { | ||
215 | struct usb_device *dev = port->serial->dev; | ||
216 | val = val & 0x00ff; | ||
217 | dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val); | ||
218 | |||
219 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, | ||
220 | MCS_WR_RTYPE, val, reg, NULL, 0, | ||
221 | MOS_WDR_TIMEOUT); | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * mos7840_get_reg_sync | ||
226 | * To set the Uart register by calling usb_fill_control_urb function by | ||
227 | * passing usb_rcvctrlpipe function as parameter. | ||
228 | */ | ||
229 | |||
230 | static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, | ||
231 | __u16 * val) | ||
232 | { | ||
233 | struct usb_device *dev = port->serial->dev; | ||
234 | int ret = 0; | ||
235 | |||
236 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, | ||
237 | MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH, | ||
238 | MOS_WDR_TIMEOUT); | ||
239 | dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val); | ||
240 | *val = (*val) & 0x00ff; | ||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * mos7840_set_uart_reg | ||
246 | * To set the Uart register by calling usb_fill_control_urb function by | ||
247 | * passing usb_sndctrlpipe function as parameter. | ||
248 | */ | ||
249 | |||
250 | static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, | ||
251 | __u16 val) | ||
252 | { | ||
253 | |||
254 | struct usb_device *dev = port->serial->dev; | ||
255 | val = val & 0x00ff; | ||
256 | // For the UART control registers, the application number need to be Or'ed | ||
257 | if (mos7840_num_ports == 4) { | ||
258 | val |= | ||
259 | (((__u16) port->number - (__u16) (port->serial->minor)) + | ||
260 | 1) << 8; | ||
261 | dbg("mos7840_set_uart_reg application number is %x\n", val); | ||
262 | } else { | ||
263 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { | ||
264 | val |= | ||
265 | (((__u16) port->number - | ||
266 | (__u16) (port->serial->minor)) + 1) << 8; | ||
267 | dbg("mos7840_set_uart_reg application number is %x\n", | ||
268 | val); | ||
269 | } else { | ||
270 | val |= | ||
271 | (((__u16) port->number - | ||
272 | (__u16) (port->serial->minor)) + 2) << 8; | ||
273 | dbg("mos7840_set_uart_reg application number is %x\n", | ||
274 | val); | ||
275 | } | ||
276 | } | ||
277 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, | ||
278 | MCS_WR_RTYPE, val, reg, NULL, 0, | ||
279 | MOS_WDR_TIMEOUT); | ||
280 | |||
281 | } | ||
282 | |||
283 | /* | ||
284 | * mos7840_get_uart_reg | ||
285 | * To set the Control register by calling usb_fill_control_urb function | ||
286 | * by passing usb_rcvctrlpipe function as parameter. | ||
287 | */ | ||
288 | static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, | ||
289 | __u16 * val) | ||
290 | { | ||
291 | struct usb_device *dev = port->serial->dev; | ||
292 | int ret = 0; | ||
293 | __u16 Wval; | ||
294 | |||
295 | //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); | ||
296 | /*Wval is same as application number */ | ||
297 | if (mos7840_num_ports == 4) { | ||
298 | Wval = | ||
299 | (((__u16) port->number - (__u16) (port->serial->minor)) + | ||
300 | 1) << 8; | ||
301 | dbg("mos7840_get_uart_reg application number is %x\n", Wval); | ||
302 | } else { | ||
303 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { | ||
304 | Wval = | ||
305 | (((__u16) port->number - | ||
306 | (__u16) (port->serial->minor)) + 1) << 8; | ||
307 | dbg("mos7840_get_uart_reg application number is %x\n", | ||
308 | Wval); | ||
309 | } else { | ||
310 | Wval = | ||
311 | (((__u16) port->number - | ||
312 | (__u16) (port->serial->minor)) + 2) << 8; | ||
313 | dbg("mos7840_get_uart_reg application number is %x\n", | ||
314 | Wval); | ||
315 | } | ||
316 | } | ||
317 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, | ||
318 | MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH, | ||
319 | MOS_WDR_TIMEOUT); | ||
320 | *val = (*val) & 0x00ff; | ||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | static void mos7840_dump_serial_port(struct moschip_port *mos7840_port) | ||
325 | { | ||
326 | |||
327 | dbg("***************************************\n"); | ||
328 | dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset); | ||
329 | dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset); | ||
330 | dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset); | ||
331 | dbg("***************************************\n"); | ||
332 | |||
333 | } | ||
334 | |||
335 | /************************************************************************/ | ||
336 | /************************************************************************/ | ||
337 | /* I N T E R F A C E F U N C T I O N S */ | ||
338 | /* I N T E R F A C E F U N C T I O N S */ | ||
339 | /************************************************************************/ | ||
340 | /************************************************************************/ | ||
341 | |||
342 | static inline void mos7840_set_port_private(struct usb_serial_port *port, | ||
343 | struct moschip_port *data) | ||
344 | { | ||
345 | usb_set_serial_port_data(port, (void *)data); | ||
346 | } | ||
347 | |||
348 | static inline struct moschip_port *mos7840_get_port_private(struct | ||
349 | usb_serial_port | ||
350 | *port) | ||
351 | { | ||
352 | return (struct moschip_port *)usb_get_serial_port_data(port); | ||
353 | } | ||
354 | |||
355 | static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) | ||
356 | { | ||
357 | struct moschip_port *mos7840_port; | ||
358 | struct async_icount *icount; | ||
359 | mos7840_port = port; | ||
360 | icount = &mos7840_port->icount; | ||
361 | if (new_msr & | ||
362 | (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI | | ||
363 | MOS_MSR_DELTA_CD)) { | ||
364 | icount = &mos7840_port->icount; | ||
365 | |||
366 | /* update input line counters */ | ||
367 | if (new_msr & MOS_MSR_DELTA_CTS) { | ||
368 | icount->cts++; | ||
369 | } | ||
370 | if (new_msr & MOS_MSR_DELTA_DSR) { | ||
371 | icount->dsr++; | ||
372 | } | ||
373 | if (new_msr & MOS_MSR_DELTA_CD) { | ||
374 | icount->dcd++; | ||
375 | } | ||
376 | if (new_msr & MOS_MSR_DELTA_RI) { | ||
377 | icount->rng++; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) | ||
385 | { | ||
386 | struct async_icount *icount; | ||
387 | |||
388 | dbg("%s - %02x", __FUNCTION__, new_lsr); | ||
389 | |||
390 | if (new_lsr & SERIAL_LSR_BI) { | ||
391 | // | ||
392 | // Parity and Framing errors only count if they | ||
393 | // occur exclusive of a break being | ||
394 | // received. | ||
395 | // | ||
396 | new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI); | ||
397 | } | ||
398 | |||
399 | /* update input line counters */ | ||
400 | icount = &port->icount; | ||
401 | if (new_lsr & SERIAL_LSR_BI) { | ||
402 | icount->brk++; | ||
403 | } | ||
404 | if (new_lsr & SERIAL_LSR_OE) { | ||
405 | icount->overrun++; | ||
406 | } | ||
407 | if (new_lsr & SERIAL_LSR_PE) { | ||
408 | icount->parity++; | ||
409 | } | ||
410 | if (new_lsr & SERIAL_LSR_FE) { | ||
411 | icount->frame++; | ||
412 | } | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | /************************************************************************/ | ||
418 | /************************************************************************/ | ||
419 | /* U S B C A L L B A C K F U N C T I O N S */ | ||
420 | /* U S B C A L L B A C K F U N C T I O N S */ | ||
421 | /************************************************************************/ | ||
422 | /************************************************************************/ | ||
423 | |||
424 | static void mos7840_control_callback(struct urb *urb, struct pt_regs *regs) | ||
425 | { | ||
426 | unsigned char *data; | ||
427 | struct moschip_port *mos7840_port; | ||
428 | __u8 regval = 0x0; | ||
429 | |||
430 | if (!urb) { | ||
431 | dbg("%s", "Invalid Pointer !!!!:\n"); | ||
432 | return; | ||
433 | } | ||
434 | |||
435 | switch (urb->status) { | ||
436 | case 0: | ||
437 | /* success */ | ||
438 | break; | ||
439 | case -ECONNRESET: | ||
440 | case -ENOENT: | ||
441 | case -ESHUTDOWN: | ||
442 | /* this urb is terminated, clean up */ | ||
443 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, | ||
444 | urb->status); | ||
445 | return; | ||
446 | default: | ||
447 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, | ||
448 | urb->status); | ||
449 | goto exit; | ||
450 | } | ||
451 | |||
452 | mos7840_port = (struct moschip_port *)urb->context; | ||
453 | |||
454 | dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length); | ||
455 | dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__, | ||
456 | mos7840_port->MsrLsr, mos7840_port->port_num); | ||
457 | data = urb->transfer_buffer; | ||
458 | regval = (__u8) data[0]; | ||
459 | dbg("%s data is %x\n", __FUNCTION__, regval); | ||
460 | if (mos7840_port->MsrLsr == 0) | ||
461 | mos7840_handle_new_msr(mos7840_port, regval); | ||
462 | else if (mos7840_port->MsrLsr == 1) | ||
463 | mos7840_handle_new_lsr(mos7840_port, regval); | ||
464 | |||
465 | exit: | ||
466 | return; | ||
467 | } | ||
468 | |||
469 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | ||
470 | __u16 * val) | ||
471 | { | ||
472 | struct usb_device *dev = mcs->port->serial->dev; | ||
473 | struct usb_ctrlrequest *dr = NULL; | ||
474 | unsigned char *buffer = NULL; | ||
475 | int ret = 0; | ||
476 | buffer = (__u8 *) mcs->ctrl_buf; | ||
477 | |||
478 | // dr=(struct usb_ctrlrequest *)(buffer); | ||
479 | dr = (void *)(buffer + 2); | ||
480 | dr->bRequestType = MCS_RD_RTYPE; | ||
481 | dr->bRequest = MCS_RDREQ; | ||
482 | dr->wValue = cpu_to_le16(Wval); //0; | ||
483 | dr->wIndex = cpu_to_le16(reg); | ||
484 | dr->wLength = cpu_to_le16(2); | ||
485 | |||
486 | usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0), | ||
487 | (unsigned char *)dr, buffer, 2, | ||
488 | mos7840_control_callback, mcs); | ||
489 | mcs->control_urb->transfer_buffer_length = 2; | ||
490 | ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC); | ||
491 | return ret; | ||
492 | } | ||
493 | |||
494 | /***************************************************************************** | ||
495 | * mos7840_interrupt_callback | ||
496 | * this is the callback function for when we have received data on the | ||
497 | * interrupt endpoint. | ||
498 | *****************************************************************************/ | ||
499 | |||
500 | static void mos7840_interrupt_callback(struct urb *urb, struct pt_regs *regs) | ||
501 | { | ||
502 | int result; | ||
503 | int length; | ||
504 | struct moschip_port *mos7840_port; | ||
505 | struct usb_serial *serial; | ||
506 | __u16 Data; | ||
507 | unsigned char *data; | ||
508 | __u8 sp[5], st; | ||
509 | int i; | ||
510 | __u16 wval; | ||
511 | |||
512 | dbg("%s", " : Entering\n"); | ||
513 | if (!urb) { | ||
514 | dbg("%s", "Invalid Pointer !!!!:\n"); | ||
515 | return; | ||
516 | } | ||
517 | |||
518 | switch (urb->status) { | ||
519 | case 0: | ||
520 | /* success */ | ||
521 | break; | ||
522 | case -ECONNRESET: | ||
523 | case -ENOENT: | ||
524 | case -ESHUTDOWN: | ||
525 | /* this urb is terminated, clean up */ | ||
526 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, | ||
527 | urb->status); | ||
528 | return; | ||
529 | default: | ||
530 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, | ||
531 | urb->status); | ||
532 | goto exit; | ||
533 | } | ||
534 | |||
535 | length = urb->actual_length; | ||
536 | data = urb->transfer_buffer; | ||
537 | |||
538 | serial = (struct usb_serial *)urb->context; | ||
539 | |||
540 | /* Moschip get 5 bytes | ||
541 | * Byte 1 IIR Port 1 (port.number is 0) | ||
542 | * Byte 2 IIR Port 2 (port.number is 1) | ||
543 | * Byte 3 IIR Port 3 (port.number is 2) | ||
544 | * Byte 4 IIR Port 4 (port.number is 3) | ||
545 | * Byte 5 FIFO status for both */ | ||
546 | |||
547 | if (length && length > 5) { | ||
548 | dbg("%s \n", "Wrong data !!!"); | ||
549 | return; | ||
550 | } | ||
551 | |||
552 | sp[0] = (__u8) data[0]; | ||
553 | sp[1] = (__u8) data[1]; | ||
554 | sp[2] = (__u8) data[2]; | ||
555 | sp[3] = (__u8) data[3]; | ||
556 | st = (__u8) data[4]; | ||
557 | |||
558 | for (i = 0; i < serial->num_ports; i++) { | ||
559 | mos7840_port = mos7840_get_port_private(serial->port[i]); | ||
560 | wval = | ||
561 | (((__u16) serial->port[i]->number - | ||
562 | (__u16) (serial->minor)) + 1) << 8; | ||
563 | if (mos7840_port->open) { | ||
564 | if (sp[i] & 0x01) { | ||
565 | dbg("SP%d No Interrupt !!!\n", i); | ||
566 | } else { | ||
567 | switch (sp[i] & 0x0f) { | ||
568 | case SERIAL_IIR_RLS: | ||
569 | dbg("Serial Port %d: Receiver status error or ", i); | ||
570 | dbg("address bit detected in 9-bit mode\n"); | ||
571 | mos7840_port->MsrLsr = 1; | ||
572 | mos7840_get_reg(mos7840_port, wval, | ||
573 | LINE_STATUS_REGISTER, | ||
574 | &Data); | ||
575 | break; | ||
576 | case SERIAL_IIR_MS: | ||
577 | dbg("Serial Port %d: Modem status change\n", i); | ||
578 | mos7840_port->MsrLsr = 0; | ||
579 | mos7840_get_reg(mos7840_port, wval, | ||
580 | MODEM_STATUS_REGISTER, | ||
581 | &Data); | ||
582 | break; | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | exit: | ||
588 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
589 | if (result) { | ||
590 | dev_err(&urb->dev->dev, | ||
591 | "%s - Error %d submitting interrupt urb\n", | ||
592 | __FUNCTION__, result); | ||
593 | } | ||
594 | |||
595 | return; | ||
596 | |||
597 | } | ||
598 | |||
599 | static int mos7840_port_paranoia_check(struct usb_serial_port *port, | ||
600 | const char *function) | ||
601 | { | ||
602 | if (!port) { | ||
603 | dbg("%s - port == NULL", function); | ||
604 | return -1; | ||
605 | } | ||
606 | if (!port->serial) { | ||
607 | dbg("%s - port->serial == NULL", function); | ||
608 | return -1; | ||
609 | } | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | /* Inline functions to check the sanity of a pointer that is passed to us */ | ||
615 | static int mos7840_serial_paranoia_check(struct usb_serial *serial, | ||
616 | const char *function) | ||
617 | { | ||
618 | if (!serial) { | ||
619 | dbg("%s - serial == NULL", function); | ||
620 | return -1; | ||
621 | } | ||
622 | if (!serial->type) { | ||
623 | dbg("%s - serial->type == NULL!", function); | ||
624 | return -1; | ||
625 | } | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port, | ||
631 | const char *function) | ||
632 | { | ||
633 | /* if no port was specified, or it fails a paranoia check */ | ||
634 | if (!port || | ||
635 | mos7840_port_paranoia_check(port, function) || | ||
636 | mos7840_serial_paranoia_check(port->serial, function)) { | ||
637 | /* then say that we don't have a valid usb_serial thing, which will * end up genrating -ENODEV return values */ | ||
638 | return NULL; | ||
639 | } | ||
640 | |||
641 | return port->serial; | ||
642 | } | ||
643 | |||
644 | /***************************************************************************** | ||
645 | * mos7840_bulk_in_callback | ||
646 | * this is the callback function for when we have received data on the | ||
647 | * bulk in endpoint. | ||
648 | *****************************************************************************/ | ||
649 | |||
650 | static void mos7840_bulk_in_callback(struct urb *urb, struct pt_regs *regs) | ||
651 | { | ||
652 | int status; | ||
653 | unsigned char *data; | ||
654 | struct usb_serial *serial; | ||
655 | struct usb_serial_port *port; | ||
656 | struct moschip_port *mos7840_port; | ||
657 | struct tty_struct *tty; | ||
658 | |||
659 | if (!urb) { | ||
660 | dbg("%s", "Invalid Pointer !!!!:\n"); | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | if (urb->status) { | ||
665 | dbg("nonzero read bulk status received: %d", urb->status); | ||
666 | return; | ||
667 | } | ||
668 | |||
669 | mos7840_port = (struct moschip_port *)urb->context; | ||
670 | if (!mos7840_port) { | ||
671 | dbg("%s", "NULL mos7840_port pointer \n"); | ||
672 | return; | ||
673 | } | ||
674 | |||
675 | port = (struct usb_serial_port *)mos7840_port->port; | ||
676 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
677 | dbg("%s", "Port Paranoia failed \n"); | ||
678 | return; | ||
679 | } | ||
680 | |||
681 | serial = mos7840_get_usb_serial(port, __FUNCTION__); | ||
682 | if (!serial) { | ||
683 | dbg("%s\n", "Bad serial pointer "); | ||
684 | return; | ||
685 | } | ||
686 | |||
687 | dbg("%s\n", "Entering... \n"); | ||
688 | |||
689 | data = urb->transfer_buffer; | ||
690 | |||
691 | dbg("%s", "Entering ........... \n"); | ||
692 | |||
693 | if (urb->actual_length) { | ||
694 | tty = mos7840_port->port->tty; | ||
695 | if (tty) { | ||
696 | tty_buffer_request_room(tty, urb->actual_length); | ||
697 | tty_insert_flip_string(tty, data, urb->actual_length); | ||
698 | dbg(" %s \n", data); | ||
699 | tty_flip_buffer_push(tty); | ||
700 | } | ||
701 | mos7840_port->icount.rx += urb->actual_length; | ||
702 | dbg("mos7840_port->icount.rx is %d:\n", | ||
703 | mos7840_port->icount.rx); | ||
704 | } | ||
705 | |||
706 | if (!mos7840_port->read_urb) { | ||
707 | dbg("%s", "URB KILLED !!!\n"); | ||
708 | return; | ||
709 | } | ||
710 | |||
711 | if (mos7840_port->read_urb->status != -EINPROGRESS) { | ||
712 | mos7840_port->read_urb->dev = serial->dev; | ||
713 | |||
714 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | ||
715 | |||
716 | if (status) { | ||
717 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | ||
718 | status); | ||
719 | } | ||
720 | } | ||
721 | } | ||
722 | |||
723 | /***************************************************************************** | ||
724 | * mos7840_bulk_out_data_callback | ||
725 | * this is the callback function for when we have finished sending serial data | ||
726 | * on the bulk out endpoint. | ||
727 | *****************************************************************************/ | ||
728 | |||
729 | static void mos7840_bulk_out_data_callback(struct urb *urb, | ||
730 | struct pt_regs *regs) | ||
731 | { | ||
732 | struct moschip_port *mos7840_port; | ||
733 | struct tty_struct *tty; | ||
734 | if (!urb) { | ||
735 | dbg("%s", "Invalid Pointer !!!!:\n"); | ||
736 | return; | ||
737 | } | ||
738 | |||
739 | if (urb->status) { | ||
740 | dbg("nonzero write bulk status received:%d\n", urb->status); | ||
741 | return; | ||
742 | } | ||
743 | |||
744 | mos7840_port = (struct moschip_port *)urb->context; | ||
745 | if (!mos7840_port) { | ||
746 | dbg("%s", "NULL mos7840_port pointer \n"); | ||
747 | return; | ||
748 | } | ||
749 | |||
750 | if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) { | ||
751 | dbg("%s", "Port Paranoia failed \n"); | ||
752 | return; | ||
753 | } | ||
754 | |||
755 | dbg("%s \n", "Entering ........."); | ||
756 | |||
757 | tty = mos7840_port->port->tty; | ||
758 | |||
759 | if (tty && mos7840_port->open) { | ||
760 | /* let the tty driver wakeup if it has a special * | ||
761 | * write_wakeup function */ | ||
762 | |||
763 | if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) | ||
764 | && tty->ldisc.write_wakeup) { | ||
765 | (tty->ldisc.write_wakeup) (tty); | ||
766 | } | ||
767 | |||
768 | /* tell the tty driver that something has changed */ | ||
769 | wake_up_interruptible(&tty->write_wait); | ||
770 | } | ||
771 | |||
772 | } | ||
773 | |||
774 | /************************************************************************/ | ||
775 | /* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */ | ||
776 | /************************************************************************/ | ||
777 | #ifdef MCSSerialProbe | ||
778 | static int mos7840_serial_probe(struct usb_serial *serial, | ||
779 | const struct usb_device_id *id) | ||
780 | { | ||
781 | |||
782 | /*need to implement the mode_reg reading and updating\ | ||
783 | structures usb_serial_ device_type\ | ||
784 | (i.e num_ports, num_bulkin,bulkout etc) */ | ||
785 | /* Also we can update the changes attach */ | ||
786 | return 1; | ||
787 | } | ||
788 | #endif | ||
789 | |||
790 | /***************************************************************************** | ||
791 | * mos7840_open | ||
792 | * this function is called by the tty driver when a port is opened | ||
793 | * If successful, we return 0 | ||
794 | * Otherwise we return a negative error number. | ||
795 | *****************************************************************************/ | ||
796 | |||
797 | static int mos7840_open(struct usb_serial_port *port, struct file *filp) | ||
798 | { | ||
799 | int response; | ||
800 | int j; | ||
801 | struct usb_serial *serial; | ||
802 | struct urb *urb; | ||
803 | __u16 Data; | ||
804 | int status; | ||
805 | struct moschip_port *mos7840_port; | ||
806 | |||
807 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
808 | dbg("%s", "Port Paranoia failed \n"); | ||
809 | return -ENODEV; | ||
810 | } | ||
811 | |||
812 | mos7840_num_open_ports++; | ||
813 | serial = port->serial; | ||
814 | |||
815 | if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) { | ||
816 | dbg("%s", "Serial Paranoia failed \n"); | ||
817 | return -ENODEV; | ||
818 | } | ||
819 | |||
820 | mos7840_port = mos7840_get_port_private(port); | ||
821 | |||
822 | if (mos7840_port == NULL) | ||
823 | return -ENODEV; | ||
824 | |||
825 | usb_clear_halt(serial->dev, port->write_urb->pipe); | ||
826 | usb_clear_halt(serial->dev, port->read_urb->pipe); | ||
827 | |||
828 | /* Initialising the write urb pool */ | ||
829 | for (j = 0; j < NUM_URBS; ++j) { | ||
830 | urb = usb_alloc_urb(0, SLAB_ATOMIC); | ||
831 | mos7840_port->write_urb_pool[j] = urb; | ||
832 | |||
833 | if (urb == NULL) { | ||
834 | err("No more urbs???"); | ||
835 | continue; | ||
836 | } | ||
837 | |||
838 | urb->transfer_buffer = NULL; | ||
839 | urb->transfer_buffer = | ||
840 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); | ||
841 | if (!urb->transfer_buffer) { | ||
842 | err("%s-out of memory for urb buffers.", __FUNCTION__); | ||
843 | continue; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | /***************************************************************************** | ||
848 | * Initialize MCS7840 -- Write Init values to corresponding Registers | ||
849 | * | ||
850 | * Register Index | ||
851 | * 1 : IER | ||
852 | * 2 : FCR | ||
853 | * 3 : LCR | ||
854 | * 4 : MCR | ||
855 | * | ||
856 | * 0x08 : SP1/2 Control Reg | ||
857 | *****************************************************************************/ | ||
858 | |||
859 | //NEED to check the following Block | ||
860 | |||
861 | status = 0; | ||
862 | Data = 0x0; | ||
863 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); | ||
864 | if (status < 0) { | ||
865 | dbg("Reading Spreg failed\n"); | ||
866 | return -1; | ||
867 | } | ||
868 | Data |= 0x80; | ||
869 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | ||
870 | if (status < 0) { | ||
871 | dbg("writing Spreg failed\n"); | ||
872 | return -1; | ||
873 | } | ||
874 | |||
875 | Data &= ~0x80; | ||
876 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | ||
877 | if (status < 0) { | ||
878 | dbg("writing Spreg failed\n"); | ||
879 | return -1; | ||
880 | } | ||
881 | //End of block to be checked | ||
882 | |||
883 | status = 0; | ||
884 | Data = 0x0; | ||
885 | status = | ||
886 | mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); | ||
887 | if (status < 0) { | ||
888 | dbg("Reading Controlreg failed\n"); | ||
889 | return -1; | ||
890 | } | ||
891 | Data |= 0x08; //Driver done bit | ||
892 | Data |= 0x20; //rx_disable | ||
893 | status = 0; | ||
894 | status = | ||
895 | mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); | ||
896 | if (status < 0) { | ||
897 | dbg("writing Controlreg failed\n"); | ||
898 | return -1; | ||
899 | } | ||
900 | //do register settings here | ||
901 | // Set all regs to the device default values. | ||
902 | //////////////////////////////////// | ||
903 | // First Disable all interrupts. | ||
904 | //////////////////////////////////// | ||
905 | |||
906 | Data = 0x00; | ||
907 | status = 0; | ||
908 | status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
909 | if (status < 0) { | ||
910 | dbg("disableing interrupts failed\n"); | ||
911 | return -1; | ||
912 | } | ||
913 | // Set FIFO_CONTROL_REGISTER to the default value | ||
914 | Data = 0x00; | ||
915 | status = 0; | ||
916 | status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
917 | if (status < 0) { | ||
918 | dbg("Writing FIFO_CONTROL_REGISTER failed\n"); | ||
919 | return -1; | ||
920 | } | ||
921 | |||
922 | Data = 0xcf; | ||
923 | status = 0; | ||
924 | status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
925 | if (status < 0) { | ||
926 | dbg("Writing FIFO_CONTROL_REGISTER failed\n"); | ||
927 | return -1; | ||
928 | } | ||
929 | |||
930 | Data = 0x03; | ||
931 | status = 0; | ||
932 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
933 | mos7840_port->shadowLCR = Data; | ||
934 | |||
935 | Data = 0x0b; | ||
936 | status = 0; | ||
937 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
938 | mos7840_port->shadowMCR = Data; | ||
939 | |||
940 | Data = 0x00; | ||
941 | status = 0; | ||
942 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | ||
943 | mos7840_port->shadowLCR = Data; | ||
944 | |||
945 | Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80 | ||
946 | status = 0; | ||
947 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
948 | |||
949 | Data = 0x0c; | ||
950 | status = 0; | ||
951 | status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); | ||
952 | |||
953 | Data = 0x0; | ||
954 | status = 0; | ||
955 | status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); | ||
956 | |||
957 | Data = 0x00; | ||
958 | status = 0; | ||
959 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | ||
960 | |||
961 | Data = Data & ~SERIAL_LCR_DLAB; | ||
962 | status = 0; | ||
963 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
964 | mos7840_port->shadowLCR = Data; | ||
965 | |||
966 | //clearing Bulkin and Bulkout Fifo | ||
967 | Data = 0x0; | ||
968 | status = 0; | ||
969 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); | ||
970 | |||
971 | Data = Data | 0x0c; | ||
972 | status = 0; | ||
973 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | ||
974 | |||
975 | Data = Data & ~0x0c; | ||
976 | status = 0; | ||
977 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | ||
978 | //Finally enable all interrupts | ||
979 | Data = 0x0; | ||
980 | Data = 0x0c; | ||
981 | status = 0; | ||
982 | status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
983 | |||
984 | //clearing rx_disable | ||
985 | Data = 0x0; | ||
986 | status = 0; | ||
987 | status = | ||
988 | mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); | ||
989 | Data = Data & ~0x20; | ||
990 | status = 0; | ||
991 | status = | ||
992 | mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); | ||
993 | |||
994 | // rx_negate | ||
995 | Data = 0x0; | ||
996 | status = 0; | ||
997 | status = | ||
998 | mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); | ||
999 | Data = Data | 0x10; | ||
1000 | status = 0; | ||
1001 | status = | ||
1002 | mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); | ||
1003 | |||
1004 | /* force low_latency on so that our tty_push actually forces * | ||
1005 | * the data through,otherwise it is scheduled, and with * | ||
1006 | * high data rates (like with OHCI) data can get lost. */ | ||
1007 | |||
1008 | if (port->tty) | ||
1009 | port->tty->low_latency = 1; | ||
1010 | /* Check to see if we've set up our endpoint info yet * | ||
1011 | * (can't set it up in mos7840_startup as the structures * | ||
1012 | * were not set up at that time.) */ | ||
1013 | if (mos7840_num_open_ports == 1) { | ||
1014 | if (serial->port[0]->interrupt_in_buffer == NULL) { | ||
1015 | |||
1016 | /* set up interrupt urb */ | ||
1017 | |||
1018 | usb_fill_int_urb(serial->port[0]->interrupt_in_urb, | ||
1019 | serial->dev, | ||
1020 | usb_rcvintpipe(serial->dev, | ||
1021 | serial->port[0]-> | ||
1022 | interrupt_in_endpointAddress), | ||
1023 | serial->port[0]->interrupt_in_buffer, | ||
1024 | serial->port[0]->interrupt_in_urb-> | ||
1025 | transfer_buffer_length, | ||
1026 | mos7840_interrupt_callback, | ||
1027 | serial, | ||
1028 | serial->port[0]->interrupt_in_urb-> | ||
1029 | interval); | ||
1030 | |||
1031 | /* start interrupt read for mos7840 * | ||
1032 | * will continue as long as mos7840 is connected */ | ||
1033 | |||
1034 | response = | ||
1035 | usb_submit_urb(serial->port[0]->interrupt_in_urb, | ||
1036 | GFP_KERNEL); | ||
1037 | if (response) { | ||
1038 | err("%s - Error %d submitting interrupt urb", | ||
1039 | __FUNCTION__, response); | ||
1040 | } | ||
1041 | |||
1042 | } | ||
1043 | |||
1044 | } | ||
1045 | |||
1046 | /* see if we've set up our endpoint info yet * | ||
1047 | * (can't set it up in mos7840_startup as the * | ||
1048 | * structures were not set up at that time.) */ | ||
1049 | |||
1050 | dbg("port number is %d \n", port->number); | ||
1051 | dbg("serial number is %d \n", port->serial->minor); | ||
1052 | dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress); | ||
1053 | dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress); | ||
1054 | dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress); | ||
1055 | dbg("port's number in the device is %d\n", mos7840_port->port_num); | ||
1056 | mos7840_port->read_urb = port->read_urb; | ||
1057 | |||
1058 | /* set up our bulk in urb */ | ||
1059 | |||
1060 | usb_fill_bulk_urb(mos7840_port->read_urb, | ||
1061 | serial->dev, | ||
1062 | usb_rcvbulkpipe(serial->dev, | ||
1063 | port->bulk_in_endpointAddress), | ||
1064 | port->bulk_in_buffer, | ||
1065 | mos7840_port->read_urb->transfer_buffer_length, | ||
1066 | mos7840_bulk_in_callback, mos7840_port); | ||
1067 | |||
1068 | dbg("mos7840_open: bulkin endpoint is %d\n", | ||
1069 | port->bulk_in_endpointAddress); | ||
1070 | response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL); | ||
1071 | if (response) { | ||
1072 | err("%s - Error %d submitting control urb", __FUNCTION__, | ||
1073 | response); | ||
1074 | } | ||
1075 | |||
1076 | /* initialize our wait queues */ | ||
1077 | init_waitqueue_head(&mos7840_port->wait_chase); | ||
1078 | init_waitqueue_head(&mos7840_port->delta_msr_wait); | ||
1079 | |||
1080 | /* initialize our icount structure */ | ||
1081 | memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); | ||
1082 | |||
1083 | /* initialize our port settings */ | ||
1084 | mos7840_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */ | ||
1085 | /* send a open port command */ | ||
1086 | mos7840_port->open = 1; | ||
1087 | //mos7840_change_port_settings(mos7840_port,old_termios); | ||
1088 | mos7840_port->icount.tx = 0; | ||
1089 | mos7840_port->icount.rx = 0; | ||
1090 | |||
1091 | dbg("\n\nusb_serial serial:%x mos7840_port:%x\n usb_serial_port port:%x\n\n", (unsigned int)serial, (unsigned int)mos7840_port, (unsigned int)port); | ||
1092 | |||
1093 | return 0; | ||
1094 | |||
1095 | } | ||
1096 | |||
1097 | /***************************************************************************** | ||
1098 | * mos7840_chars_in_buffer | ||
1099 | * this function is called by the tty driver when it wants to know how many | ||
1100 | * bytes of data we currently have outstanding in the port (data that has | ||
1101 | * been written, but hasn't made it out the port yet) | ||
1102 | * If successful, we return the number of bytes left to be written in the | ||
1103 | * system, | ||
1104 | * Otherwise we return a negative error number. | ||
1105 | *****************************************************************************/ | ||
1106 | |||
1107 | static int mos7840_chars_in_buffer(struct usb_serial_port *port) | ||
1108 | { | ||
1109 | int i; | ||
1110 | int chars = 0; | ||
1111 | struct moschip_port *mos7840_port; | ||
1112 | |||
1113 | dbg("%s \n", " mos7840_chars_in_buffer:entering ..........."); | ||
1114 | |||
1115 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1116 | dbg("%s", "Invalid port \n"); | ||
1117 | return -1; | ||
1118 | } | ||
1119 | |||
1120 | mos7840_port = mos7840_get_port_private(port); | ||
1121 | if (mos7840_port == NULL) { | ||
1122 | dbg("%s \n", "mos7840_break:leaving ..........."); | ||
1123 | return -1; | ||
1124 | } | ||
1125 | |||
1126 | for (i = 0; i < NUM_URBS; ++i) { | ||
1127 | if (mos7840_port->write_urb_pool[i]->status == -EINPROGRESS) { | ||
1128 | chars += URB_TRANSFER_BUFFER_SIZE; | ||
1129 | } | ||
1130 | } | ||
1131 | dbg("%s - returns %d", __FUNCTION__, chars); | ||
1132 | return (chars); | ||
1133 | |||
1134 | } | ||
1135 | |||
1136 | /************************************************************************ | ||
1137 | * | ||
1138 | * mos7840_block_until_tx_empty | ||
1139 | * | ||
1140 | * This function will block the close until one of the following: | ||
1141 | * 1. TX count are 0 | ||
1142 | * 2. The mos7840 has stopped | ||
1143 | * 3. A timout of 3 seconds without activity has expired | ||
1144 | * | ||
1145 | ************************************************************************/ | ||
1146 | static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port) | ||
1147 | { | ||
1148 | int timeout = HZ / 10; | ||
1149 | int wait = 30; | ||
1150 | int count; | ||
1151 | |||
1152 | while (1) { | ||
1153 | |||
1154 | count = mos7840_chars_in_buffer(mos7840_port->port); | ||
1155 | |||
1156 | /* Check for Buffer status */ | ||
1157 | if (count <= 0) { | ||
1158 | return; | ||
1159 | } | ||
1160 | |||
1161 | /* Block the thread for a while */ | ||
1162 | interruptible_sleep_on_timeout(&mos7840_port->wait_chase, | ||
1163 | timeout); | ||
1164 | |||
1165 | /* No activity.. count down section */ | ||
1166 | wait--; | ||
1167 | if (wait == 0) { | ||
1168 | dbg("%s - TIMEOUT", __FUNCTION__); | ||
1169 | return; | ||
1170 | } else { | ||
1171 | /* Reset timout value back to seconds */ | ||
1172 | wait = 30; | ||
1173 | } | ||
1174 | } | ||
1175 | } | ||
1176 | |||
1177 | /***************************************************************************** | ||
1178 | * mos7840_close | ||
1179 | * this function is called by the tty driver when a port is closed | ||
1180 | *****************************************************************************/ | ||
1181 | |||
1182 | static void mos7840_close(struct usb_serial_port *port, struct file *filp) | ||
1183 | { | ||
1184 | struct usb_serial *serial; | ||
1185 | struct moschip_port *mos7840_port; | ||
1186 | int j; | ||
1187 | __u16 Data; | ||
1188 | |||
1189 | dbg("%s\n", "mos7840_close:entering..."); | ||
1190 | |||
1191 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1192 | dbg("%s", "Port Paranoia failed \n"); | ||
1193 | return; | ||
1194 | } | ||
1195 | |||
1196 | serial = mos7840_get_usb_serial(port, __FUNCTION__); | ||
1197 | if (!serial) { | ||
1198 | dbg("%s", "Serial Paranoia failed \n"); | ||
1199 | return; | ||
1200 | } | ||
1201 | |||
1202 | mos7840_port = mos7840_get_port_private(port); | ||
1203 | |||
1204 | if (mos7840_port == NULL) { | ||
1205 | return; | ||
1206 | } | ||
1207 | |||
1208 | for (j = 0; j < NUM_URBS; ++j) | ||
1209 | usb_kill_urb(mos7840_port->write_urb_pool[j]); | ||
1210 | |||
1211 | /* Freeing Write URBs */ | ||
1212 | for (j = 0; j < NUM_URBS; ++j) { | ||
1213 | if (mos7840_port->write_urb_pool[j]) { | ||
1214 | if (mos7840_port->write_urb_pool[j]->transfer_buffer) | ||
1215 | kfree(mos7840_port->write_urb_pool[j]-> | ||
1216 | transfer_buffer); | ||
1217 | |||
1218 | usb_free_urb(mos7840_port->write_urb_pool[j]); | ||
1219 | } | ||
1220 | } | ||
1221 | |||
1222 | if (serial->dev) { | ||
1223 | /* flush and block until tx is empty */ | ||
1224 | mos7840_block_until_tx_empty(mos7840_port); | ||
1225 | } | ||
1226 | |||
1227 | /* While closing port, shutdown all bulk read, write * | ||
1228 | * and interrupt read if they exists */ | ||
1229 | if (serial->dev) { | ||
1230 | |||
1231 | if (mos7840_port->write_urb) { | ||
1232 | dbg("%s", "Shutdown bulk write\n"); | ||
1233 | usb_kill_urb(mos7840_port->write_urb); | ||
1234 | } | ||
1235 | |||
1236 | if (mos7840_port->read_urb) { | ||
1237 | dbg("%s", "Shutdown bulk read\n"); | ||
1238 | usb_kill_urb(mos7840_port->read_urb); | ||
1239 | } | ||
1240 | if ((&mos7840_port->control_urb)) { | ||
1241 | dbg("%s", "Shutdown control read\n"); | ||
1242 | // usb_kill_urb (mos7840_port->control_urb); | ||
1243 | |||
1244 | } | ||
1245 | } | ||
1246 | // if(mos7840_port->ctrl_buf != NULL) | ||
1247 | // kfree(mos7840_port->ctrl_buf); | ||
1248 | mos7840_num_open_ports--; | ||
1249 | dbg("mos7840_num_open_ports in close%d:in port%d\n", | ||
1250 | mos7840_num_open_ports, port->number); | ||
1251 | if (mos7840_num_open_ports == 0) { | ||
1252 | if (serial->port[0]->interrupt_in_urb) { | ||
1253 | dbg("%s", "Shutdown interrupt_in_urb\n"); | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | if (mos7840_port->write_urb) { | ||
1258 | /* if this urb had a transfer buffer already (old tx) free it */ | ||
1259 | |||
1260 | if (mos7840_port->write_urb->transfer_buffer != NULL) { | ||
1261 | kfree(mos7840_port->write_urb->transfer_buffer); | ||
1262 | } | ||
1263 | usb_free_urb(mos7840_port->write_urb); | ||
1264 | } | ||
1265 | |||
1266 | Data = 0x0; | ||
1267 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
1268 | |||
1269 | Data = 0x00; | ||
1270 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
1271 | |||
1272 | mos7840_port->open = 0; | ||
1273 | |||
1274 | dbg("%s \n", "Leaving ............"); | ||
1275 | } | ||
1276 | |||
1277 | /************************************************************************ | ||
1278 | * | ||
1279 | * mos7840_block_until_chase_response | ||
1280 | * | ||
1281 | * This function will block the close until one of the following: | ||
1282 | * 1. Response to our Chase comes from mos7840 | ||
1283 | * 2. A timout of 10 seconds without activity has expired | ||
1284 | * (1K of mos7840 data @ 2400 baud ==> 4 sec to empty) | ||
1285 | * | ||
1286 | ************************************************************************/ | ||
1287 | |||
1288 | static void mos7840_block_until_chase_response(struct moschip_port | ||
1289 | *mos7840_port) | ||
1290 | { | ||
1291 | int timeout = 1 * HZ; | ||
1292 | int wait = 10; | ||
1293 | int count; | ||
1294 | |||
1295 | while (1) { | ||
1296 | count = mos7840_chars_in_buffer(mos7840_port->port); | ||
1297 | |||
1298 | /* Check for Buffer status */ | ||
1299 | if (count <= 0) { | ||
1300 | return; | ||
1301 | } | ||
1302 | |||
1303 | /* Block the thread for a while */ | ||
1304 | interruptible_sleep_on_timeout(&mos7840_port->wait_chase, | ||
1305 | timeout); | ||
1306 | /* No activity.. count down section */ | ||
1307 | wait--; | ||
1308 | if (wait == 0) { | ||
1309 | dbg("%s - TIMEOUT", __FUNCTION__); | ||
1310 | return; | ||
1311 | } else { | ||
1312 | /* Reset timout value back to seconds */ | ||
1313 | wait = 10; | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1317 | } | ||
1318 | |||
1319 | /***************************************************************************** | ||
1320 | * mos7840_break | ||
1321 | * this function sends a break to the port | ||
1322 | *****************************************************************************/ | ||
1323 | static void mos7840_break(struct usb_serial_port *port, int break_state) | ||
1324 | { | ||
1325 | unsigned char data; | ||
1326 | struct usb_serial *serial; | ||
1327 | struct moschip_port *mos7840_port; | ||
1328 | |||
1329 | dbg("%s \n", "Entering ..........."); | ||
1330 | dbg("mos7840_break: Start\n"); | ||
1331 | |||
1332 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1333 | dbg("%s", "Port Paranoia failed \n"); | ||
1334 | return; | ||
1335 | } | ||
1336 | |||
1337 | serial = mos7840_get_usb_serial(port, __FUNCTION__); | ||
1338 | if (!serial) { | ||
1339 | dbg("%s", "Serial Paranoia failed \n"); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | mos7840_port = mos7840_get_port_private(port); | ||
1344 | |||
1345 | if (mos7840_port == NULL) { | ||
1346 | return; | ||
1347 | } | ||
1348 | |||
1349 | if (serial->dev) { | ||
1350 | |||
1351 | /* flush and block until tx is empty */ | ||
1352 | mos7840_block_until_chase_response(mos7840_port); | ||
1353 | } | ||
1354 | |||
1355 | if (break_state == -1) { | ||
1356 | data = mos7840_port->shadowLCR | LCR_SET_BREAK; | ||
1357 | } else { | ||
1358 | data = mos7840_port->shadowLCR & ~LCR_SET_BREAK; | ||
1359 | } | ||
1360 | |||
1361 | mos7840_port->shadowLCR = data; | ||
1362 | dbg("mcs7840_break mos7840_port->shadowLCR is %x\n", | ||
1363 | mos7840_port->shadowLCR); | ||
1364 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, | ||
1365 | mos7840_port->shadowLCR); | ||
1366 | |||
1367 | return; | ||
1368 | } | ||
1369 | |||
1370 | /***************************************************************************** | ||
1371 | * mos7840_write_room | ||
1372 | * this function is called by the tty driver when it wants to know how many | ||
1373 | * bytes of data we can accept for a specific port. | ||
1374 | * If successful, we return the amount of room that we have for this port | ||
1375 | * Otherwise we return a negative error number. | ||
1376 | *****************************************************************************/ | ||
1377 | |||
1378 | static int mos7840_write_room(struct usb_serial_port *port) | ||
1379 | { | ||
1380 | int i; | ||
1381 | int room = 0; | ||
1382 | struct moschip_port *mos7840_port; | ||
1383 | |||
1384 | dbg("%s \n", " mos7840_write_room:entering ..........."); | ||
1385 | |||
1386 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1387 | dbg("%s", "Invalid port \n"); | ||
1388 | dbg("%s \n", " mos7840_write_room:leaving ..........."); | ||
1389 | return -1; | ||
1390 | } | ||
1391 | |||
1392 | mos7840_port = mos7840_get_port_private(port); | ||
1393 | if (mos7840_port == NULL) { | ||
1394 | dbg("%s \n", "mos7840_break:leaving ..........."); | ||
1395 | return -1; | ||
1396 | } | ||
1397 | |||
1398 | for (i = 0; i < NUM_URBS; ++i) { | ||
1399 | if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) { | ||
1400 | room += URB_TRANSFER_BUFFER_SIZE; | ||
1401 | } | ||
1402 | } | ||
1403 | |||
1404 | dbg("%s - returns %d", __FUNCTION__, room); | ||
1405 | return (room); | ||
1406 | |||
1407 | } | ||
1408 | |||
1409 | /***************************************************************************** | ||
1410 | * mos7840_write | ||
1411 | * this function is called by the tty driver when data should be written to | ||
1412 | * the port. | ||
1413 | * If successful, we return the number of bytes written, otherwise we | ||
1414 | * return a negative error number. | ||
1415 | *****************************************************************************/ | ||
1416 | |||
1417 | static int mos7840_write(struct usb_serial_port *port, | ||
1418 | const unsigned char *data, int count) | ||
1419 | { | ||
1420 | int status; | ||
1421 | int i; | ||
1422 | int bytes_sent = 0; | ||
1423 | int transfer_size; | ||
1424 | int from_user = 0; | ||
1425 | |||
1426 | struct moschip_port *mos7840_port; | ||
1427 | struct usb_serial *serial; | ||
1428 | struct urb *urb; | ||
1429 | //__u16 Data; | ||
1430 | const unsigned char *current_position = data; | ||
1431 | unsigned char *data1; | ||
1432 | dbg("%s \n", "entering ..........."); | ||
1433 | //dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR); | ||
1434 | |||
1435 | #ifdef NOTMOS7840 | ||
1436 | Data = 0x00; | ||
1437 | status = 0; | ||
1438 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | ||
1439 | mos7840_port->shadowLCR = Data; | ||
1440 | dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data); | ||
1441 | dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", | ||
1442 | mos7840_port->shadowLCR); | ||
1443 | |||
1444 | //Data = 0x03; | ||
1445 | //status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); | ||
1446 | //mos7840_port->shadowLCR=Data;//Need to add later | ||
1447 | |||
1448 | Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80 | ||
1449 | status = 0; | ||
1450 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
1451 | |||
1452 | //Data = 0x0c; | ||
1453 | //status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); | ||
1454 | Data = 0x00; | ||
1455 | status = 0; | ||
1456 | status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data); | ||
1457 | dbg("mos7840_write:DLL value is %x\n", Data); | ||
1458 | |||
1459 | Data = 0x0; | ||
1460 | status = 0; | ||
1461 | status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data); | ||
1462 | dbg("mos7840_write:DLM value is %x\n", Data); | ||
1463 | |||
1464 | Data = Data & ~SERIAL_LCR_DLAB; | ||
1465 | dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", | ||
1466 | mos7840_port->shadowLCR); | ||
1467 | status = 0; | ||
1468 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
1469 | #endif | ||
1470 | |||
1471 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1472 | dbg("%s", "Port Paranoia failed \n"); | ||
1473 | return -1; | ||
1474 | } | ||
1475 | |||
1476 | serial = port->serial; | ||
1477 | if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) { | ||
1478 | dbg("%s", "Serial Paranoia failed \n"); | ||
1479 | return -1; | ||
1480 | } | ||
1481 | |||
1482 | mos7840_port = mos7840_get_port_private(port); | ||
1483 | if (mos7840_port == NULL) { | ||
1484 | dbg("%s", "mos7840_port is NULL\n"); | ||
1485 | return -1; | ||
1486 | } | ||
1487 | |||
1488 | /* try to find a free urb in the list */ | ||
1489 | urb = NULL; | ||
1490 | |||
1491 | for (i = 0; i < NUM_URBS; ++i) { | ||
1492 | if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) { | ||
1493 | urb = mos7840_port->write_urb_pool[i]; | ||
1494 | dbg("\nURB:%d", i); | ||
1495 | break; | ||
1496 | } | ||
1497 | } | ||
1498 | |||
1499 | if (urb == NULL) { | ||
1500 | dbg("%s - no more free urbs", __FUNCTION__); | ||
1501 | goto exit; | ||
1502 | } | ||
1503 | |||
1504 | if (urb->transfer_buffer == NULL) { | ||
1505 | urb->transfer_buffer = | ||
1506 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); | ||
1507 | |||
1508 | if (urb->transfer_buffer == NULL) { | ||
1509 | err("%s no more kernel memory...", __FUNCTION__); | ||
1510 | goto exit; | ||
1511 | } | ||
1512 | } | ||
1513 | transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); | ||
1514 | |||
1515 | if (from_user) { | ||
1516 | if (copy_from_user | ||
1517 | (urb->transfer_buffer, current_position, transfer_size)) { | ||
1518 | bytes_sent = -EFAULT; | ||
1519 | goto exit; | ||
1520 | } | ||
1521 | } else { | ||
1522 | memcpy(urb->transfer_buffer, current_position, transfer_size); | ||
1523 | } | ||
1524 | |||
1525 | /* fill urb with data and submit */ | ||
1526 | usb_fill_bulk_urb(urb, | ||
1527 | serial->dev, | ||
1528 | usb_sndbulkpipe(serial->dev, | ||
1529 | port->bulk_out_endpointAddress), | ||
1530 | urb->transfer_buffer, | ||
1531 | transfer_size, | ||
1532 | mos7840_bulk_out_data_callback, mos7840_port); | ||
1533 | |||
1534 | data1 = urb->transfer_buffer; | ||
1535 | dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress); | ||
1536 | |||
1537 | /* send it down the pipe */ | ||
1538 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
1539 | |||
1540 | if (status) { | ||
1541 | err("%s - usb_submit_urb(write bulk) failed with status = %d", | ||
1542 | __FUNCTION__, status); | ||
1543 | bytes_sent = status; | ||
1544 | goto exit; | ||
1545 | } | ||
1546 | bytes_sent = transfer_size; | ||
1547 | mos7840_port->icount.tx += transfer_size; | ||
1548 | dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); | ||
1549 | exit: | ||
1550 | |||
1551 | return bytes_sent; | ||
1552 | |||
1553 | } | ||
1554 | |||
1555 | /***************************************************************************** | ||
1556 | * mos7840_throttle | ||
1557 | * this function is called by the tty driver when it wants to stop the data | ||
1558 | * being read from the port. | ||
1559 | *****************************************************************************/ | ||
1560 | |||
1561 | static void mos7840_throttle(struct usb_serial_port *port) | ||
1562 | { | ||
1563 | struct moschip_port *mos7840_port; | ||
1564 | struct tty_struct *tty; | ||
1565 | int status; | ||
1566 | |||
1567 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1568 | dbg("%s", "Invalid port \n"); | ||
1569 | return; | ||
1570 | } | ||
1571 | |||
1572 | dbg("- port %d\n", port->number); | ||
1573 | |||
1574 | mos7840_port = mos7840_get_port_private(port); | ||
1575 | |||
1576 | if (mos7840_port == NULL) | ||
1577 | return; | ||
1578 | |||
1579 | if (!mos7840_port->open) { | ||
1580 | dbg("%s\n", "port not opened"); | ||
1581 | return; | ||
1582 | } | ||
1583 | |||
1584 | dbg("%s", "Entering .......... \n"); | ||
1585 | |||
1586 | tty = port->tty; | ||
1587 | if (!tty) { | ||
1588 | dbg("%s - no tty available", __FUNCTION__); | ||
1589 | return; | ||
1590 | } | ||
1591 | |||
1592 | /* if we are implementing XON/XOFF, send the stop character */ | ||
1593 | if (I_IXOFF(tty)) { | ||
1594 | unsigned char stop_char = STOP_CHAR(tty); | ||
1595 | status = mos7840_write(port, &stop_char, 1); | ||
1596 | if (status <= 0) { | ||
1597 | return; | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | /* if we are implementing RTS/CTS, toggle that line */ | ||
1602 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1603 | mos7840_port->shadowMCR &= ~MCR_RTS; | ||
1604 | status = 0; | ||
1605 | status = | ||
1606 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, | ||
1607 | mos7840_port->shadowMCR); | ||
1608 | |||
1609 | if (status < 0) { | ||
1610 | return; | ||
1611 | } | ||
1612 | } | ||
1613 | |||
1614 | return; | ||
1615 | } | ||
1616 | |||
1617 | /***************************************************************************** | ||
1618 | * mos7840_unthrottle | ||
1619 | * this function is called by the tty driver when it wants to resume the data | ||
1620 | * being read from the port (called after SerialThrottle is called) | ||
1621 | *****************************************************************************/ | ||
1622 | static void mos7840_unthrottle(struct usb_serial_port *port) | ||
1623 | { | ||
1624 | struct tty_struct *tty; | ||
1625 | int status; | ||
1626 | struct moschip_port *mos7840_port = mos7840_get_port_private(port); | ||
1627 | |||
1628 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1629 | dbg("%s", "Invalid port \n"); | ||
1630 | return; | ||
1631 | } | ||
1632 | |||
1633 | if (mos7840_port == NULL) | ||
1634 | return; | ||
1635 | |||
1636 | if (!mos7840_port->open) { | ||
1637 | dbg("%s - port not opened", __FUNCTION__); | ||
1638 | return; | ||
1639 | } | ||
1640 | |||
1641 | dbg("%s", "Entering .......... \n"); | ||
1642 | |||
1643 | tty = port->tty; | ||
1644 | if (!tty) { | ||
1645 | dbg("%s - no tty available", __FUNCTION__); | ||
1646 | return; | ||
1647 | } | ||
1648 | |||
1649 | /* if we are implementing XON/XOFF, send the start character */ | ||
1650 | if (I_IXOFF(tty)) { | ||
1651 | unsigned char start_char = START_CHAR(tty); | ||
1652 | status = mos7840_write(port, &start_char, 1); | ||
1653 | if (status <= 0) { | ||
1654 | return; | ||
1655 | } | ||
1656 | } | ||
1657 | |||
1658 | /* if we are implementing RTS/CTS, toggle that line */ | ||
1659 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1660 | mos7840_port->shadowMCR |= MCR_RTS; | ||
1661 | status = 0; | ||
1662 | status = | ||
1663 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, | ||
1664 | mos7840_port->shadowMCR); | ||
1665 | if (status < 0) { | ||
1666 | return; | ||
1667 | } | ||
1668 | } | ||
1669 | |||
1670 | return; | ||
1671 | } | ||
1672 | |||
1673 | static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file) | ||
1674 | { | ||
1675 | struct moschip_port *mos7840_port; | ||
1676 | unsigned int result; | ||
1677 | __u16 msr; | ||
1678 | __u16 mcr; | ||
1679 | int status = 0; | ||
1680 | mos7840_port = mos7840_get_port_private(port); | ||
1681 | |||
1682 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1683 | |||
1684 | if (mos7840_port == NULL) | ||
1685 | return -ENODEV; | ||
1686 | |||
1687 | status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); | ||
1688 | status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); | ||
1689 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | ||
1690 | | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | ||
1691 | | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) | ||
1692 | | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) | ||
1693 | | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0) | ||
1694 | | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) | ||
1695 | | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); | ||
1696 | |||
1697 | dbg("%s - 0x%04X", __FUNCTION__, result); | ||
1698 | |||
1699 | return result; | ||
1700 | } | ||
1701 | |||
1702 | static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file, | ||
1703 | unsigned int set, unsigned int clear) | ||
1704 | { | ||
1705 | struct moschip_port *mos7840_port; | ||
1706 | unsigned int mcr; | ||
1707 | unsigned int status; | ||
1708 | |||
1709 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1710 | |||
1711 | mos7840_port = mos7840_get_port_private(port); | ||
1712 | |||
1713 | if (mos7840_port == NULL) | ||
1714 | return -ENODEV; | ||
1715 | |||
1716 | mcr = mos7840_port->shadowMCR; | ||
1717 | if (clear & TIOCM_RTS) | ||
1718 | mcr &= ~MCR_RTS; | ||
1719 | if (clear & TIOCM_DTR) | ||
1720 | mcr &= ~MCR_DTR; | ||
1721 | if (clear & TIOCM_LOOP) | ||
1722 | mcr &= ~MCR_LOOPBACK; | ||
1723 | |||
1724 | if (set & TIOCM_RTS) | ||
1725 | mcr |= MCR_RTS; | ||
1726 | if (set & TIOCM_DTR) | ||
1727 | mcr |= MCR_DTR; | ||
1728 | if (set & TIOCM_LOOP) | ||
1729 | mcr |= MCR_LOOPBACK; | ||
1730 | |||
1731 | mos7840_port->shadowMCR = mcr; | ||
1732 | |||
1733 | status = 0; | ||
1734 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr); | ||
1735 | if (status < 0) { | ||
1736 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); | ||
1737 | return -1; | ||
1738 | } | ||
1739 | |||
1740 | return 0; | ||
1741 | } | ||
1742 | |||
1743 | /***************************************************************************** | ||
1744 | * mos7840_calc_baud_rate_divisor | ||
1745 | * this function calculates the proper baud rate divisor for the specified | ||
1746 | * baud rate. | ||
1747 | *****************************************************************************/ | ||
1748 | static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, | ||
1749 | __u16 * clk_sel_val) | ||
1750 | { | ||
1751 | |||
1752 | dbg("%s - %d", __FUNCTION__, baudRate); | ||
1753 | |||
1754 | if (baudRate <= 115200) { | ||
1755 | *divisor = 115200 / baudRate; | ||
1756 | *clk_sel_val = 0x0; | ||
1757 | } | ||
1758 | if ((baudRate > 115200) && (baudRate <= 230400)) { | ||
1759 | *divisor = 230400 / baudRate; | ||
1760 | *clk_sel_val = 0x10; | ||
1761 | } else if ((baudRate > 230400) && (baudRate <= 403200)) { | ||
1762 | *divisor = 403200 / baudRate; | ||
1763 | *clk_sel_val = 0x20; | ||
1764 | } else if ((baudRate > 403200) && (baudRate <= 460800)) { | ||
1765 | *divisor = 460800 / baudRate; | ||
1766 | *clk_sel_val = 0x30; | ||
1767 | } else if ((baudRate > 460800) && (baudRate <= 806400)) { | ||
1768 | *divisor = 806400 / baudRate; | ||
1769 | *clk_sel_val = 0x40; | ||
1770 | } else if ((baudRate > 806400) && (baudRate <= 921600)) { | ||
1771 | *divisor = 921600 / baudRate; | ||
1772 | *clk_sel_val = 0x50; | ||
1773 | } else if ((baudRate > 921600) && (baudRate <= 1572864)) { | ||
1774 | *divisor = 1572864 / baudRate; | ||
1775 | *clk_sel_val = 0x60; | ||
1776 | } else if ((baudRate > 1572864) && (baudRate <= 3145728)) { | ||
1777 | *divisor = 3145728 / baudRate; | ||
1778 | *clk_sel_val = 0x70; | ||
1779 | } | ||
1780 | return 0; | ||
1781 | |||
1782 | #ifdef NOTMCS7840 | ||
1783 | |||
1784 | for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) { | ||
1785 | if (mos7840_divisor_table[i].BaudRate == baudrate) { | ||
1786 | *divisor = mos7840_divisor_table[i].Divisor; | ||
1787 | return 0; | ||
1788 | } | ||
1789 | } | ||
1790 | |||
1791 | /* After trying for all the standard baud rates * | ||
1792 | * Try calculating the divisor for this baud rate */ | ||
1793 | |||
1794 | if (baudrate > 75 && baudrate < 230400) { | ||
1795 | /* get the divisor */ | ||
1796 | custom = (__u16) (230400L / baudrate); | ||
1797 | |||
1798 | /* Check for round off */ | ||
1799 | round1 = (__u16) (2304000L / baudrate); | ||
1800 | round = (__u16) (round1 - (custom * 10)); | ||
1801 | if (round > 4) { | ||
1802 | custom++; | ||
1803 | } | ||
1804 | *divisor = custom; | ||
1805 | |||
1806 | dbg(" Baud %d = %d\n", baudrate, custom); | ||
1807 | return 0; | ||
1808 | } | ||
1809 | |||
1810 | dbg("%s\n", " Baud calculation Failed..."); | ||
1811 | return -1; | ||
1812 | #endif | ||
1813 | } | ||
1814 | |||
1815 | /***************************************************************************** | ||
1816 | * mos7840_send_cmd_write_baud_rate | ||
1817 | * this function sends the proper command to change the baud rate of the | ||
1818 | * specified port. | ||
1819 | *****************************************************************************/ | ||
1820 | |||
1821 | static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, | ||
1822 | int baudRate) | ||
1823 | { | ||
1824 | int divisor = 0; | ||
1825 | int status; | ||
1826 | __u16 Data; | ||
1827 | unsigned char number; | ||
1828 | __u16 clk_sel_val; | ||
1829 | struct usb_serial_port *port; | ||
1830 | |||
1831 | if (mos7840_port == NULL) | ||
1832 | return -1; | ||
1833 | |||
1834 | port = (struct usb_serial_port *)mos7840_port->port; | ||
1835 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1836 | dbg("%s", "Invalid port \n"); | ||
1837 | return -1; | ||
1838 | } | ||
1839 | |||
1840 | if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) { | ||
1841 | dbg("%s", "Invalid Serial \n"); | ||
1842 | return -1; | ||
1843 | } | ||
1844 | |||
1845 | dbg("%s", "Entering .......... \n"); | ||
1846 | |||
1847 | number = mos7840_port->port->number - mos7840_port->port->serial->minor; | ||
1848 | |||
1849 | dbg("%s - port = %d, baud = %d", __FUNCTION__, | ||
1850 | mos7840_port->port->number, baudRate); | ||
1851 | //reset clk_uart_sel in spregOffset | ||
1852 | if (baudRate > 115200) { | ||
1853 | #ifdef HW_flow_control | ||
1854 | //NOTE: need to see the pther register to modify | ||
1855 | //setting h/w flow control bit to 1; | ||
1856 | status = 0; | ||
1857 | Data = 0x2b; | ||
1858 | mos7840_port->shadowMCR = Data; | ||
1859 | status = | ||
1860 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
1861 | if (status < 0) { | ||
1862 | dbg("Writing spreg failed in set_serial_baud\n"); | ||
1863 | return -1; | ||
1864 | } | ||
1865 | #endif | ||
1866 | |||
1867 | } else { | ||
1868 | #ifdef HW_flow_control | ||
1869 | //setting h/w flow control bit to 0; | ||
1870 | status = 0; | ||
1871 | Data = 0xb; | ||
1872 | mos7840_port->shadowMCR = Data; | ||
1873 | status = | ||
1874 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
1875 | if (status < 0) { | ||
1876 | dbg("Writing spreg failed in set_serial_baud\n"); | ||
1877 | return -1; | ||
1878 | } | ||
1879 | #endif | ||
1880 | |||
1881 | } | ||
1882 | |||
1883 | if (1) //baudRate <= 115200) | ||
1884 | { | ||
1885 | clk_sel_val = 0x0; | ||
1886 | Data = 0x0; | ||
1887 | status = 0; | ||
1888 | status = | ||
1889 | mos7840_calc_baud_rate_divisor(baudRate, &divisor, | ||
1890 | &clk_sel_val); | ||
1891 | status = | ||
1892 | mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, | ||
1893 | &Data); | ||
1894 | if (status < 0) { | ||
1895 | dbg("reading spreg failed in set_serial_baud\n"); | ||
1896 | return -1; | ||
1897 | } | ||
1898 | Data = (Data & 0x8f) | clk_sel_val; | ||
1899 | status = 0; | ||
1900 | status = | ||
1901 | mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | ||
1902 | if (status < 0) { | ||
1903 | dbg("Writing spreg failed in set_serial_baud\n"); | ||
1904 | return -1; | ||
1905 | } | ||
1906 | /* Calculate the Divisor */ | ||
1907 | |||
1908 | if (status) { | ||
1909 | err("%s - bad baud rate", __FUNCTION__); | ||
1910 | dbg("%s\n", "bad baud rate"); | ||
1911 | return status; | ||
1912 | } | ||
1913 | /* Enable access to divisor latch */ | ||
1914 | Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB; | ||
1915 | mos7840_port->shadowLCR = Data; | ||
1916 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
1917 | |||
1918 | /* Write the divisor */ | ||
1919 | Data = (unsigned char)(divisor & 0xff); | ||
1920 | dbg("set_serial_baud Value to write DLL is %x\n", Data); | ||
1921 | mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); | ||
1922 | |||
1923 | Data = (unsigned char)((divisor & 0xff00) >> 8); | ||
1924 | dbg("set_serial_baud Value to write DLM is %x\n", Data); | ||
1925 | mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); | ||
1926 | |||
1927 | /* Disable access to divisor latch */ | ||
1928 | Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB; | ||
1929 | mos7840_port->shadowLCR = Data; | ||
1930 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
1931 | |||
1932 | } | ||
1933 | |||
1934 | return status; | ||
1935 | } | ||
1936 | |||
1937 | /***************************************************************************** | ||
1938 | * mos7840_change_port_settings | ||
1939 | * This routine is called to set the UART on the device to match | ||
1940 | * the specified new settings. | ||
1941 | *****************************************************************************/ | ||
1942 | |||
1943 | static void mos7840_change_port_settings(struct moschip_port *mos7840_port, | ||
1944 | struct termios *old_termios) | ||
1945 | { | ||
1946 | struct tty_struct *tty; | ||
1947 | int baud; | ||
1948 | unsigned cflag; | ||
1949 | unsigned iflag; | ||
1950 | __u8 lData; | ||
1951 | __u8 lParity; | ||
1952 | __u8 lStop; | ||
1953 | int status; | ||
1954 | __u16 Data; | ||
1955 | struct usb_serial_port *port; | ||
1956 | struct usb_serial *serial; | ||
1957 | |||
1958 | if (mos7840_port == NULL) | ||
1959 | return; | ||
1960 | |||
1961 | port = (struct usb_serial_port *)mos7840_port->port; | ||
1962 | |||
1963 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
1964 | dbg("%s", "Invalid port \n"); | ||
1965 | return; | ||
1966 | } | ||
1967 | |||
1968 | if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) { | ||
1969 | dbg("%s", "Invalid Serial \n"); | ||
1970 | return; | ||
1971 | } | ||
1972 | |||
1973 | serial = port->serial; | ||
1974 | |||
1975 | dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number); | ||
1976 | |||
1977 | if (!mos7840_port->open) { | ||
1978 | dbg("%s - port not opened", __FUNCTION__); | ||
1979 | return; | ||
1980 | } | ||
1981 | |||
1982 | tty = mos7840_port->port->tty; | ||
1983 | |||
1984 | if ((!tty) || (!tty->termios)) { | ||
1985 | dbg("%s - no tty structures", __FUNCTION__); | ||
1986 | return; | ||
1987 | } | ||
1988 | |||
1989 | dbg("%s", "Entering .......... \n"); | ||
1990 | |||
1991 | lData = LCR_BITS_8; | ||
1992 | lStop = LCR_STOP_1; | ||
1993 | lParity = LCR_PAR_NONE; | ||
1994 | |||
1995 | cflag = tty->termios->c_cflag; | ||
1996 | iflag = tty->termios->c_iflag; | ||
1997 | |||
1998 | /* Change the number of bits */ | ||
1999 | if (cflag & CSIZE) { | ||
2000 | switch (cflag & CSIZE) { | ||
2001 | case CS5: | ||
2002 | lData = LCR_BITS_5; | ||
2003 | break; | ||
2004 | |||
2005 | case CS6: | ||
2006 | lData = LCR_BITS_6; | ||
2007 | break; | ||
2008 | |||
2009 | case CS7: | ||
2010 | lData = LCR_BITS_7; | ||
2011 | break; | ||
2012 | default: | ||
2013 | case CS8: | ||
2014 | lData = LCR_BITS_8; | ||
2015 | break; | ||
2016 | } | ||
2017 | } | ||
2018 | /* Change the Parity bit */ | ||
2019 | if (cflag & PARENB) { | ||
2020 | if (cflag & PARODD) { | ||
2021 | lParity = LCR_PAR_ODD; | ||
2022 | dbg("%s - parity = odd", __FUNCTION__); | ||
2023 | } else { | ||
2024 | lParity = LCR_PAR_EVEN; | ||
2025 | dbg("%s - parity = even", __FUNCTION__); | ||
2026 | } | ||
2027 | |||
2028 | } else { | ||
2029 | dbg("%s - parity = none", __FUNCTION__); | ||
2030 | } | ||
2031 | |||
2032 | if (cflag & CMSPAR) { | ||
2033 | lParity = lParity | 0x20; | ||
2034 | } | ||
2035 | |||
2036 | /* Change the Stop bit */ | ||
2037 | if (cflag & CSTOPB) { | ||
2038 | lStop = LCR_STOP_2; | ||
2039 | dbg("%s - stop bits = 2", __FUNCTION__); | ||
2040 | } else { | ||
2041 | lStop = LCR_STOP_1; | ||
2042 | dbg("%s - stop bits = 1", __FUNCTION__); | ||
2043 | } | ||
2044 | |||
2045 | /* Update the LCR with the correct value */ | ||
2046 | mos7840_port->shadowLCR &= | ||
2047 | ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); | ||
2048 | mos7840_port->shadowLCR |= (lData | lParity | lStop); | ||
2049 | |||
2050 | dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n", | ||
2051 | mos7840_port->shadowLCR); | ||
2052 | /* Disable Interrupts */ | ||
2053 | Data = 0x00; | ||
2054 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
2055 | |||
2056 | Data = 0x00; | ||
2057 | mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
2058 | |||
2059 | Data = 0xcf; | ||
2060 | mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
2061 | |||
2062 | /* Send the updated LCR value to the mos7840 */ | ||
2063 | Data = mos7840_port->shadowLCR; | ||
2064 | |||
2065 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
2066 | |||
2067 | Data = 0x00b; | ||
2068 | mos7840_port->shadowMCR = Data; | ||
2069 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
2070 | Data = 0x00b; | ||
2071 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
2072 | |||
2073 | /* set up the MCR register and send it to the mos7840 */ | ||
2074 | |||
2075 | mos7840_port->shadowMCR = MCR_MASTER_IE; | ||
2076 | if (cflag & CBAUD) { | ||
2077 | mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS); | ||
2078 | } | ||
2079 | |||
2080 | if (cflag & CRTSCTS) { | ||
2081 | mos7840_port->shadowMCR |= (MCR_XON_ANY); | ||
2082 | |||
2083 | } else { | ||
2084 | mos7840_port->shadowMCR &= ~(MCR_XON_ANY); | ||
2085 | } | ||
2086 | |||
2087 | Data = mos7840_port->shadowMCR; | ||
2088 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
2089 | |||
2090 | /* Determine divisor based on baud rate */ | ||
2091 | baud = tty_get_baud_rate(tty); | ||
2092 | |||
2093 | if (!baud) { | ||
2094 | /* pick a default, any default... */ | ||
2095 | dbg("%s\n", "Picked default baud..."); | ||
2096 | baud = 9600; | ||
2097 | } | ||
2098 | |||
2099 | dbg("%s - baud rate = %d", __FUNCTION__, baud); | ||
2100 | status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud); | ||
2101 | |||
2102 | /* Enable Interrupts */ | ||
2103 | Data = 0x0c; | ||
2104 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
2105 | |||
2106 | if (mos7840_port->read_urb->status != -EINPROGRESS) { | ||
2107 | mos7840_port->read_urb->dev = serial->dev; | ||
2108 | |||
2109 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | ||
2110 | |||
2111 | if (status) { | ||
2112 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | ||
2113 | status); | ||
2114 | } | ||
2115 | } | ||
2116 | wake_up(&mos7840_port->delta_msr_wait); | ||
2117 | mos7840_port->delta_msr_cond = 1; | ||
2118 | dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n", | ||
2119 | mos7840_port->shadowLCR); | ||
2120 | |||
2121 | return; | ||
2122 | } | ||
2123 | |||
2124 | /***************************************************************************** | ||
2125 | * mos7840_set_termios | ||
2126 | * this function is called by the tty driver when it wants to change | ||
2127 | * the termios structure | ||
2128 | *****************************************************************************/ | ||
2129 | |||
2130 | static void mos7840_set_termios(struct usb_serial_port *port, | ||
2131 | struct termios *old_termios) | ||
2132 | { | ||
2133 | int status; | ||
2134 | unsigned int cflag; | ||
2135 | struct usb_serial *serial; | ||
2136 | struct moschip_port *mos7840_port; | ||
2137 | struct tty_struct *tty; | ||
2138 | dbg("mos7840_set_termios: START\n"); | ||
2139 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
2140 | dbg("%s", "Invalid port \n"); | ||
2141 | return; | ||
2142 | } | ||
2143 | |||
2144 | serial = port->serial; | ||
2145 | |||
2146 | if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) { | ||
2147 | dbg("%s", "Invalid Serial \n"); | ||
2148 | return; | ||
2149 | } | ||
2150 | |||
2151 | mos7840_port = mos7840_get_port_private(port); | ||
2152 | |||
2153 | if (mos7840_port == NULL) | ||
2154 | return; | ||
2155 | |||
2156 | tty = port->tty; | ||
2157 | |||
2158 | if (!port->tty || !port->tty->termios) { | ||
2159 | dbg("%s - no tty or termios", __FUNCTION__); | ||
2160 | return; | ||
2161 | } | ||
2162 | |||
2163 | if (!mos7840_port->open) { | ||
2164 | dbg("%s - port not opened", __FUNCTION__); | ||
2165 | return; | ||
2166 | } | ||
2167 | |||
2168 | dbg("%s\n", "setting termios - "); | ||
2169 | |||
2170 | cflag = tty->termios->c_cflag; | ||
2171 | |||
2172 | if (!cflag) { | ||
2173 | dbg("%s %s\n", __FUNCTION__, "cflag is NULL"); | ||
2174 | return; | ||
2175 | } | ||
2176 | |||
2177 | /* check that they really want us to change something */ | ||
2178 | if (old_termios) { | ||
2179 | if ((cflag == old_termios->c_cflag) && | ||
2180 | (RELEVANT_IFLAG(tty->termios->c_iflag) == | ||
2181 | RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
2182 | dbg("%s\n", "Nothing to change"); | ||
2183 | return; | ||
2184 | } | ||
2185 | } | ||
2186 | |||
2187 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, | ||
2188 | tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); | ||
2189 | |||
2190 | if (old_termios) { | ||
2191 | dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, | ||
2192 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); | ||
2193 | } | ||
2194 | |||
2195 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2196 | |||
2197 | /* change the port settings to the new ones specified */ | ||
2198 | |||
2199 | mos7840_change_port_settings(mos7840_port, old_termios); | ||
2200 | |||
2201 | if (!mos7840_port->read_urb) { | ||
2202 | dbg("%s", "URB KILLED !!!!!\n"); | ||
2203 | return; | ||
2204 | } | ||
2205 | |||
2206 | if (mos7840_port->read_urb->status != -EINPROGRESS) { | ||
2207 | mos7840_port->read_urb->dev = serial->dev; | ||
2208 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | ||
2209 | if (status) { | ||
2210 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | ||
2211 | status); | ||
2212 | } | ||
2213 | } | ||
2214 | return; | ||
2215 | } | ||
2216 | |||
2217 | /***************************************************************************** | ||
2218 | * mos7840_get_lsr_info - get line status register info | ||
2219 | * | ||
2220 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
2221 | * is emptied. On bus types like RS485, the transmitter must | ||
2222 | * release the bus after transmitting. This must be done when | ||
2223 | * the transmit shift register is empty, not be done when the | ||
2224 | * transmit holding register is empty. This functionality | ||
2225 | * allows an RS485 driver to be written in user space. | ||
2226 | *****************************************************************************/ | ||
2227 | |||
2228 | static int mos7840_get_lsr_info(struct moschip_port *mos7840_port, | ||
2229 | unsigned int *value) | ||
2230 | { | ||
2231 | int count; | ||
2232 | unsigned int result = 0; | ||
2233 | |||
2234 | count = mos7840_chars_in_buffer(mos7840_port->port); | ||
2235 | if (count == 0) { | ||
2236 | dbg("%s -- Empty", __FUNCTION__); | ||
2237 | result = TIOCSER_TEMT; | ||
2238 | } | ||
2239 | |||
2240 | if (copy_to_user(value, &result, sizeof(int))) | ||
2241 | return -EFAULT; | ||
2242 | return 0; | ||
2243 | } | ||
2244 | |||
2245 | /***************************************************************************** | ||
2246 | * mos7840_get_bytes_avail - get number of bytes available | ||
2247 | * | ||
2248 | * Purpose: Let user call ioctl to get the count of number of bytes available. | ||
2249 | *****************************************************************************/ | ||
2250 | |||
2251 | static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port, | ||
2252 | unsigned int *value) | ||
2253 | { | ||
2254 | unsigned int result = 0; | ||
2255 | struct tty_struct *tty = mos7840_port->port->tty; | ||
2256 | |||
2257 | if (!tty) | ||
2258 | return -ENOIOCTLCMD; | ||
2259 | |||
2260 | result = tty->read_cnt; | ||
2261 | |||
2262 | dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result); | ||
2263 | if (copy_to_user(value, &result, sizeof(int))) | ||
2264 | return -EFAULT; | ||
2265 | |||
2266 | return -ENOIOCTLCMD; | ||
2267 | } | ||
2268 | |||
2269 | /***************************************************************************** | ||
2270 | * mos7840_set_modem_info | ||
2271 | * function to set modem info | ||
2272 | *****************************************************************************/ | ||
2273 | |||
2274 | static int mos7840_set_modem_info(struct moschip_port *mos7840_port, | ||
2275 | unsigned int cmd, unsigned int *value) | ||
2276 | { | ||
2277 | unsigned int mcr; | ||
2278 | unsigned int arg; | ||
2279 | __u16 Data; | ||
2280 | int status; | ||
2281 | struct usb_serial_port *port; | ||
2282 | |||
2283 | if (mos7840_port == NULL) | ||
2284 | return -1; | ||
2285 | |||
2286 | port = (struct usb_serial_port *)mos7840_port->port; | ||
2287 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
2288 | dbg("%s", "Invalid port \n"); | ||
2289 | return -1; | ||
2290 | } | ||
2291 | |||
2292 | mcr = mos7840_port->shadowMCR; | ||
2293 | |||
2294 | if (copy_from_user(&arg, value, sizeof(int))) | ||
2295 | return -EFAULT; | ||
2296 | |||
2297 | switch (cmd) { | ||
2298 | case TIOCMBIS: | ||
2299 | if (arg & TIOCM_RTS) | ||
2300 | mcr |= MCR_RTS; | ||
2301 | if (arg & TIOCM_DTR) | ||
2302 | mcr |= MCR_RTS; | ||
2303 | if (arg & TIOCM_LOOP) | ||
2304 | mcr |= MCR_LOOPBACK; | ||
2305 | break; | ||
2306 | |||
2307 | case TIOCMBIC: | ||
2308 | if (arg & TIOCM_RTS) | ||
2309 | mcr &= ~MCR_RTS; | ||
2310 | if (arg & TIOCM_DTR) | ||
2311 | mcr &= ~MCR_RTS; | ||
2312 | if (arg & TIOCM_LOOP) | ||
2313 | mcr &= ~MCR_LOOPBACK; | ||
2314 | break; | ||
2315 | |||
2316 | case TIOCMSET: | ||
2317 | /* turn off the RTS and DTR and LOOPBACK | ||
2318 | * and then only turn on what was asked to */ | ||
2319 | mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK); | ||
2320 | mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0); | ||
2321 | mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0); | ||
2322 | mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0); | ||
2323 | break; | ||
2324 | } | ||
2325 | |||
2326 | mos7840_port->shadowMCR = mcr; | ||
2327 | |||
2328 | Data = mos7840_port->shadowMCR; | ||
2329 | status = 0; | ||
2330 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
2331 | if (status < 0) { | ||
2332 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); | ||
2333 | return -1; | ||
2334 | } | ||
2335 | |||
2336 | return 0; | ||
2337 | } | ||
2338 | |||
2339 | /***************************************************************************** | ||
2340 | * mos7840_get_modem_info | ||
2341 | * function to get modem info | ||
2342 | *****************************************************************************/ | ||
2343 | |||
2344 | static int mos7840_get_modem_info(struct moschip_port *mos7840_port, | ||
2345 | unsigned int *value) | ||
2346 | { | ||
2347 | unsigned int result = 0; | ||
2348 | __u16 msr; | ||
2349 | unsigned int mcr = mos7840_port->shadowMCR; | ||
2350 | int status = 0; | ||
2351 | status = | ||
2352 | mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER, | ||
2353 | &msr); | ||
2354 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ | ||
2355 | |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ | ||
2356 | |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ | ||
2357 | |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0) /* 0x040 */ | ||
2358 | |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ | ||
2359 | |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ | ||
2360 | |||
2361 | dbg("%s -- %x", __FUNCTION__, result); | ||
2362 | |||
2363 | if (copy_to_user(value, &result, sizeof(int))) | ||
2364 | return -EFAULT; | ||
2365 | return 0; | ||
2366 | } | ||
2367 | |||
2368 | /***************************************************************************** | ||
2369 | * mos7840_get_serial_info | ||
2370 | * function to get information about serial port | ||
2371 | *****************************************************************************/ | ||
2372 | |||
2373 | static int mos7840_get_serial_info(struct moschip_port *mos7840_port, | ||
2374 | struct serial_struct *retinfo) | ||
2375 | { | ||
2376 | struct serial_struct tmp; | ||
2377 | |||
2378 | if (mos7840_port == NULL) | ||
2379 | return -1; | ||
2380 | |||
2381 | if (!retinfo) | ||
2382 | return -EFAULT; | ||
2383 | |||
2384 | memset(&tmp, 0, sizeof(tmp)); | ||
2385 | |||
2386 | tmp.type = PORT_16550A; | ||
2387 | tmp.line = mos7840_port->port->serial->minor; | ||
2388 | tmp.port = mos7840_port->port->number; | ||
2389 | tmp.irq = 0; | ||
2390 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | ||
2391 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; | ||
2392 | tmp.baud_base = 9600; | ||
2393 | tmp.close_delay = 5 * HZ; | ||
2394 | tmp.closing_wait = 30 * HZ; | ||
2395 | |||
2396 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
2397 | return -EFAULT; | ||
2398 | return 0; | ||
2399 | } | ||
2400 | |||
2401 | /***************************************************************************** | ||
2402 | * SerialIoctl | ||
2403 | * this function handles any ioctl calls to the driver | ||
2404 | *****************************************************************************/ | ||
2405 | |||
2406 | static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, | ||
2407 | unsigned int cmd, unsigned long arg) | ||
2408 | { | ||
2409 | struct moschip_port *mos7840_port; | ||
2410 | struct tty_struct *tty; | ||
2411 | |||
2412 | struct async_icount cnow; | ||
2413 | struct async_icount cprev; | ||
2414 | struct serial_icounter_struct icount; | ||
2415 | int mosret = 0; | ||
2416 | int retval; | ||
2417 | struct tty_ldisc *ld; | ||
2418 | |||
2419 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | ||
2420 | dbg("%s", "Invalid port \n"); | ||
2421 | return -1; | ||
2422 | } | ||
2423 | |||
2424 | mos7840_port = mos7840_get_port_private(port); | ||
2425 | tty = mos7840_port->port->tty; | ||
2426 | |||
2427 | if (mos7840_port == NULL) | ||
2428 | return -1; | ||
2429 | |||
2430 | dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd); | ||
2431 | |||
2432 | switch (cmd) { | ||
2433 | /* return number of bytes available */ | ||
2434 | |||
2435 | case TIOCINQ: | ||
2436 | dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number); | ||
2437 | return mos7840_get_bytes_avail(mos7840_port, | ||
2438 | (unsigned int *)arg); | ||
2439 | break; | ||
2440 | |||
2441 | case TIOCOUTQ: | ||
2442 | dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number); | ||
2443 | return put_user(tty->driver->chars_in_buffer ? | ||
2444 | tty->driver->chars_in_buffer(tty) : 0, | ||
2445 | (int __user *)arg); | ||
2446 | break; | ||
2447 | |||
2448 | case TCFLSH: | ||
2449 | retval = tty_check_change(tty); | ||
2450 | if (retval) | ||
2451 | return retval; | ||
2452 | |||
2453 | ld = tty_ldisc_ref(tty); | ||
2454 | switch (arg) { | ||
2455 | case TCIFLUSH: | ||
2456 | if (ld && ld->flush_buffer) | ||
2457 | ld->flush_buffer(tty); | ||
2458 | break; | ||
2459 | case TCIOFLUSH: | ||
2460 | if (ld && ld->flush_buffer) | ||
2461 | ld->flush_buffer(tty); | ||
2462 | /* fall through */ | ||
2463 | case TCOFLUSH: | ||
2464 | if (tty->driver->flush_buffer) | ||
2465 | tty->driver->flush_buffer(tty); | ||
2466 | break; | ||
2467 | default: | ||
2468 | tty_ldisc_deref(ld); | ||
2469 | return -EINVAL; | ||
2470 | } | ||
2471 | tty_ldisc_deref(ld); | ||
2472 | return 0; | ||
2473 | |||
2474 | case TCGETS: | ||
2475 | if (kernel_termios_to_user_termios | ||
2476 | ((struct termios __user *)arg, tty->termios)) | ||
2477 | return -EFAULT; | ||
2478 | return 0; | ||
2479 | |||
2480 | case TIOCSERGETLSR: | ||
2481 | dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number); | ||
2482 | return mos7840_get_lsr_info(mos7840_port, (unsigned int *)arg); | ||
2483 | return 0; | ||
2484 | |||
2485 | case TIOCMBIS: | ||
2486 | case TIOCMBIC: | ||
2487 | case TIOCMSET: | ||
2488 | dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__, | ||
2489 | port->number); | ||
2490 | mosret = | ||
2491 | mos7840_set_modem_info(mos7840_port, cmd, | ||
2492 | (unsigned int *)arg); | ||
2493 | return mosret; | ||
2494 | |||
2495 | case TIOCMGET: | ||
2496 | dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number); | ||
2497 | return mos7840_get_modem_info(mos7840_port, | ||
2498 | (unsigned int *)arg); | ||
2499 | |||
2500 | case TIOCGSERIAL: | ||
2501 | dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number); | ||
2502 | return mos7840_get_serial_info(mos7840_port, | ||
2503 | (struct serial_struct *)arg); | ||
2504 | |||
2505 | case TIOCSSERIAL: | ||
2506 | dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number); | ||
2507 | break; | ||
2508 | |||
2509 | case TIOCMIWAIT: | ||
2510 | dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number); | ||
2511 | cprev = mos7840_port->icount; | ||
2512 | while (1) { | ||
2513 | //interruptible_sleep_on(&mos7840_port->delta_msr_wait); | ||
2514 | mos7840_port->delta_msr_cond = 0; | ||
2515 | wait_event_interruptible(mos7840_port->delta_msr_wait, | ||
2516 | (mos7840_port-> | ||
2517 | delta_msr_cond == 1)); | ||
2518 | |||
2519 | /* see if a signal did it */ | ||
2520 | if (signal_pending(current)) | ||
2521 | return -ERESTARTSYS; | ||
2522 | cnow = mos7840_port->icount; | ||
2523 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
2524 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | ||
2525 | return -EIO; /* no change => error */ | ||
2526 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
2527 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
2528 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
2529 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { | ||
2530 | return 0; | ||
2531 | } | ||
2532 | cprev = cnow; | ||
2533 | } | ||
2534 | /* NOTREACHED */ | ||
2535 | break; | ||
2536 | |||
2537 | case TIOCGICOUNT: | ||
2538 | cnow = mos7840_port->icount; | ||
2539 | icount.cts = cnow.cts; | ||
2540 | icount.dsr = cnow.dsr; | ||
2541 | icount.rng = cnow.rng; | ||
2542 | icount.dcd = cnow.dcd; | ||
2543 | icount.rx = cnow.rx; | ||
2544 | icount.tx = cnow.tx; | ||
2545 | icount.frame = cnow.frame; | ||
2546 | icount.overrun = cnow.overrun; | ||
2547 | icount.parity = cnow.parity; | ||
2548 | icount.brk = cnow.brk; | ||
2549 | icount.buf_overrun = cnow.buf_overrun; | ||
2550 | |||
2551 | dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, | ||
2552 | port->number, icount.rx, icount.tx); | ||
2553 | if (copy_to_user((void *)arg, &icount, sizeof(icount))) | ||
2554 | return -EFAULT; | ||
2555 | return 0; | ||
2556 | |||
2557 | case TIOCEXBAUD: | ||
2558 | return 0; | ||
2559 | default: | ||
2560 | break; | ||
2561 | } | ||
2562 | |||
2563 | return -ENOIOCTLCMD; | ||
2564 | } | ||
2565 | |||
2566 | static int mos7840_calc_num_ports(struct usb_serial *serial) | ||
2567 | { | ||
2568 | |||
2569 | dbg("numberofendpoints: %d \n", | ||
2570 | (int)serial->interface->cur_altsetting->desc.bNumEndpoints); | ||
2571 | dbg("numberofendpoints: %d \n", | ||
2572 | (int)serial->interface->altsetting->desc.bNumEndpoints); | ||
2573 | if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) { | ||
2574 | mos7840_num_ports = 2; | ||
2575 | serial->type->num_ports = 2; | ||
2576 | } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) { | ||
2577 | mos7840_num_ports = 4; | ||
2578 | serial->type->num_bulk_in = 4; | ||
2579 | serial->type->num_bulk_out = 4; | ||
2580 | serial->type->num_ports = 4; | ||
2581 | } | ||
2582 | |||
2583 | return mos7840_num_ports; | ||
2584 | } | ||
2585 | |||
2586 | /**************************************************************************** | ||
2587 | * mos7840_startup | ||
2588 | ****************************************************************************/ | ||
2589 | |||
2590 | static int mos7840_startup(struct usb_serial *serial) | ||
2591 | { | ||
2592 | struct moschip_port *mos7840_port; | ||
2593 | struct usb_device *dev; | ||
2594 | int i, status; | ||
2595 | |||
2596 | __u16 Data; | ||
2597 | dbg("%s \n", " mos7840_startup :entering.........."); | ||
2598 | |||
2599 | if (!serial) { | ||
2600 | dbg("%s\n", "Invalid Handler"); | ||
2601 | return -1; | ||
2602 | } | ||
2603 | |||
2604 | dev = serial->dev; | ||
2605 | |||
2606 | dbg("%s\n", "Entering..."); | ||
2607 | |||
2608 | /* we set up the pointers to the endpoints in the mos7840_open * | ||
2609 | * function, as the structures aren't created yet. */ | ||
2610 | |||
2611 | /* set up port private structures */ | ||
2612 | for (i = 0; i < serial->num_ports; ++i) { | ||
2613 | mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL); | ||
2614 | if (mos7840_port == NULL) { | ||
2615 | err("%s - Out of memory", __FUNCTION__); | ||
2616 | return -ENOMEM; | ||
2617 | } | ||
2618 | memset(mos7840_port, 0, sizeof(struct moschip_port)); | ||
2619 | |||
2620 | /* Initialize all port interrupt end point to port 0 int endpoint * | ||
2621 | * Our device has only one interrupt end point comman to all port */ | ||
2622 | |||
2623 | mos7840_port->port = serial->port[i]; | ||
2624 | mos7840_set_port_private(serial->port[i], mos7840_port); | ||
2625 | |||
2626 | mos7840_port->port_num = ((serial->port[i]->number - | ||
2627 | (serial->port[i]->serial->minor)) + | ||
2628 | 1); | ||
2629 | |||
2630 | if (mos7840_port->port_num == 1) { | ||
2631 | mos7840_port->SpRegOffset = 0x0; | ||
2632 | mos7840_port->ControlRegOffset = 0x1; | ||
2633 | mos7840_port->DcrRegOffset = 0x4; | ||
2634 | } else if ((mos7840_port->port_num == 2) | ||
2635 | && (mos7840_num_ports == 4)) { | ||
2636 | mos7840_port->SpRegOffset = 0x8; | ||
2637 | mos7840_port->ControlRegOffset = 0x9; | ||
2638 | mos7840_port->DcrRegOffset = 0x16; | ||
2639 | } else if ((mos7840_port->port_num == 2) | ||
2640 | && (mos7840_num_ports == 2)) { | ||
2641 | mos7840_port->SpRegOffset = 0xa; | ||
2642 | mos7840_port->ControlRegOffset = 0xb; | ||
2643 | mos7840_port->DcrRegOffset = 0x19; | ||
2644 | } else if ((mos7840_port->port_num == 3) | ||
2645 | && (mos7840_num_ports == 4)) { | ||
2646 | mos7840_port->SpRegOffset = 0xa; | ||
2647 | mos7840_port->ControlRegOffset = 0xb; | ||
2648 | mos7840_port->DcrRegOffset = 0x19; | ||
2649 | } else if ((mos7840_port->port_num == 4) | ||
2650 | && (mos7840_num_ports == 4)) { | ||
2651 | mos7840_port->SpRegOffset = 0xc; | ||
2652 | mos7840_port->ControlRegOffset = 0xd; | ||
2653 | mos7840_port->DcrRegOffset = 0x1c; | ||
2654 | } | ||
2655 | mos7840_dump_serial_port(mos7840_port); | ||
2656 | |||
2657 | mos7840_set_port_private(serial->port[i], mos7840_port); | ||
2658 | |||
2659 | //enable rx_disable bit in control register | ||
2660 | |||
2661 | status = | ||
2662 | mos7840_get_reg_sync(serial->port[i], | ||
2663 | mos7840_port->ControlRegOffset, &Data); | ||
2664 | if (status < 0) { | ||
2665 | dbg("Reading ControlReg failed status-0x%x\n", status); | ||
2666 | break; | ||
2667 | } else | ||
2668 | dbg("ControlReg Reading success val is %x, status%d\n", | ||
2669 | Data, status); | ||
2670 | Data |= 0x08; //setting driver done bit | ||
2671 | Data |= 0x04; //sp1_bit to have cts change reflect in modem status reg | ||
2672 | |||
2673 | //Data |= 0x20; //rx_disable bit | ||
2674 | status = 0; | ||
2675 | status = | ||
2676 | mos7840_set_reg_sync(serial->port[i], | ||
2677 | mos7840_port->ControlRegOffset, Data); | ||
2678 | if (status < 0) { | ||
2679 | dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status); | ||
2680 | break; | ||
2681 | } else | ||
2682 | dbg("ControlReg Writing success(rx_disable) status%d\n", | ||
2683 | status); | ||
2684 | |||
2685 | //Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3 | ||
2686 | Data = 0x01; | ||
2687 | status = 0; | ||
2688 | status = | ||
2689 | mos7840_set_reg_sync(serial->port[i], | ||
2690 | (__u16) (mos7840_port->DcrRegOffset + | ||
2691 | 0), Data); | ||
2692 | if (status < 0) { | ||
2693 | dbg("Writing DCR0 failed status-0x%x\n", status); | ||
2694 | break; | ||
2695 | } else | ||
2696 | dbg("DCR0 Writing success status%d\n", status); | ||
2697 | |||
2698 | Data = 0x05; | ||
2699 | status = 0; | ||
2700 | status = | ||
2701 | mos7840_set_reg_sync(serial->port[i], | ||
2702 | (__u16) (mos7840_port->DcrRegOffset + | ||
2703 | 1), Data); | ||
2704 | if (status < 0) { | ||
2705 | dbg("Writing DCR1 failed status-0x%x\n", status); | ||
2706 | break; | ||
2707 | } else | ||
2708 | dbg("DCR1 Writing success status%d\n", status); | ||
2709 | |||
2710 | Data = 0x24; | ||
2711 | status = 0; | ||
2712 | status = | ||
2713 | mos7840_set_reg_sync(serial->port[i], | ||
2714 | (__u16) (mos7840_port->DcrRegOffset + | ||
2715 | 2), Data); | ||
2716 | if (status < 0) { | ||
2717 | dbg("Writing DCR2 failed status-0x%x\n", status); | ||
2718 | break; | ||
2719 | } else | ||
2720 | dbg("DCR2 Writing success status%d\n", status); | ||
2721 | |||
2722 | // write values in clkstart0x0 and clkmulti 0x20 | ||
2723 | Data = 0x0; | ||
2724 | status = 0; | ||
2725 | status = | ||
2726 | mos7840_set_reg_sync(serial->port[i], | ||
2727 | CLK_START_VALUE_REGISTER, Data); | ||
2728 | if (status < 0) { | ||
2729 | dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); | ||
2730 | break; | ||
2731 | } else | ||
2732 | dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status); | ||
2733 | |||
2734 | Data = 0x20; | ||
2735 | status = 0; | ||
2736 | status = | ||
2737 | mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER, | ||
2738 | Data); | ||
2739 | if (status < 0) { | ||
2740 | dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n", | ||
2741 | status); | ||
2742 | break; | ||
2743 | } else | ||
2744 | dbg("CLK_MULTI_REGISTER Writing success status%d\n", | ||
2745 | status); | ||
2746 | |||
2747 | //write value 0x0 to scratchpad register | ||
2748 | Data = 0x00; | ||
2749 | status = 0; | ||
2750 | status = | ||
2751 | mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER, | ||
2752 | Data); | ||
2753 | if (status < 0) { | ||
2754 | dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", | ||
2755 | status); | ||
2756 | break; | ||
2757 | } else | ||
2758 | dbg("SCRATCH_PAD_REGISTER Writing success status%d\n", | ||
2759 | status); | ||
2760 | |||
2761 | //Zero Length flag register | ||
2762 | if ((mos7840_port->port_num != 1) | ||
2763 | && (mos7840_num_ports == 2)) { | ||
2764 | |||
2765 | Data = 0xff; | ||
2766 | status = 0; | ||
2767 | status = mos7840_set_reg_sync(serial->port[i], | ||
2768 | (__u16) (ZLP_REG1 + | ||
2769 | ((__u16) | ||
2770 | mos7840_port-> | ||
2771 | port_num)), | ||
2772 | Data); | ||
2773 | dbg("ZLIP offset%x\n", | ||
2774 | (__u16) (ZLP_REG1 + | ||
2775 | ((__u16) mos7840_port->port_num))); | ||
2776 | if (status < 0) { | ||
2777 | dbg("Writing ZLP_REG%d failed status-0x%x\n", | ||
2778 | i + 2, status); | ||
2779 | break; | ||
2780 | } else | ||
2781 | dbg("ZLP_REG%d Writing success status%d\n", | ||
2782 | i + 2, status); | ||
2783 | } else { | ||
2784 | Data = 0xff; | ||
2785 | status = 0; | ||
2786 | status = mos7840_set_reg_sync(serial->port[i], | ||
2787 | (__u16) (ZLP_REG1 + | ||
2788 | ((__u16) | ||
2789 | mos7840_port-> | ||
2790 | port_num) - | ||
2791 | 0x1), Data); | ||
2792 | dbg("ZLIP offset%x\n", | ||
2793 | (__u16) (ZLP_REG1 + | ||
2794 | ((__u16) mos7840_port->port_num) - 0x1)); | ||
2795 | if (status < 0) { | ||
2796 | dbg("Writing ZLP_REG%d failed status-0x%x\n", | ||
2797 | i + 1, status); | ||
2798 | break; | ||
2799 | } else | ||
2800 | dbg("ZLP_REG%d Writing success status%d\n", | ||
2801 | i + 1, status); | ||
2802 | |||
2803 | } | ||
2804 | mos7840_port->control_urb = usb_alloc_urb(0, SLAB_ATOMIC); | ||
2805 | mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); | ||
2806 | |||
2807 | } | ||
2808 | |||
2809 | //Zero Length flag enable | ||
2810 | Data = 0x0f; | ||
2811 | status = 0; | ||
2812 | status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); | ||
2813 | if (status < 0) { | ||
2814 | dbg("Writing ZLP_REG5 failed status-0x%x\n", status); | ||
2815 | return -1; | ||
2816 | } else | ||
2817 | dbg("ZLP_REG5 Writing success status%d\n", status); | ||
2818 | |||
2819 | /* setting configuration feature to one */ | ||
2820 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
2821 | (__u8) 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 5 * HZ); | ||
2822 | return 0; | ||
2823 | } | ||
2824 | |||
2825 | /**************************************************************************** | ||
2826 | * mos7840_shutdown | ||
2827 | * This function is called whenever the device is removed from the usb bus. | ||
2828 | ****************************************************************************/ | ||
2829 | |||
2830 | static void mos7840_shutdown(struct usb_serial *serial) | ||
2831 | { | ||
2832 | int i; | ||
2833 | struct moschip_port *mos7840_port; | ||
2834 | dbg("%s \n", " shutdown :entering.........."); | ||
2835 | |||
2836 | if (!serial) { | ||
2837 | dbg("%s", "Invalid Handler \n"); | ||
2838 | return; | ||
2839 | } | ||
2840 | |||
2841 | /* check for the ports to be closed,close the ports and disconnect */ | ||
2842 | |||
2843 | /* free private structure allocated for serial port * | ||
2844 | * stop reads and writes on all ports */ | ||
2845 | |||
2846 | for (i = 0; i < serial->num_ports; ++i) { | ||
2847 | mos7840_port = mos7840_get_port_private(serial->port[i]); | ||
2848 | kfree(mos7840_port->ctrl_buf); | ||
2849 | usb_kill_urb(mos7840_port->control_urb); | ||
2850 | kfree(mos7840_port); | ||
2851 | mos7840_set_port_private(serial->port[i], NULL); | ||
2852 | } | ||
2853 | |||
2854 | dbg("%s\n", "Thank u :: "); | ||
2855 | |||
2856 | } | ||
2857 | |||
2858 | static struct usb_serial_driver moschip7840_4port_device = { | ||
2859 | .driver = { | ||
2860 | .owner = THIS_MODULE, | ||
2861 | .name = "mos7840", | ||
2862 | }, | ||
2863 | .description = DRIVER_DESC, | ||
2864 | .id_table = moschip_port_id_table, | ||
2865 | .num_interrupt_in = 1, //NUM_DONT_CARE,//1, | ||
2866 | #ifdef check | ||
2867 | .num_bulk_in = 4, | ||
2868 | .num_bulk_out = 4, | ||
2869 | .num_ports = 4, | ||
2870 | #endif | ||
2871 | .open = mos7840_open, | ||
2872 | .close = mos7840_close, | ||
2873 | .write = mos7840_write, | ||
2874 | .write_room = mos7840_write_room, | ||
2875 | .chars_in_buffer = mos7840_chars_in_buffer, | ||
2876 | .throttle = mos7840_throttle, | ||
2877 | .unthrottle = mos7840_unthrottle, | ||
2878 | .calc_num_ports = mos7840_calc_num_ports, | ||
2879 | #ifdef MCSSerialProbe | ||
2880 | .probe = mos7840_serial_probe, | ||
2881 | #endif | ||
2882 | .ioctl = mos7840_ioctl, | ||
2883 | .set_termios = mos7840_set_termios, | ||
2884 | .break_ctl = mos7840_break, | ||
2885 | .tiocmget = mos7840_tiocmget, | ||
2886 | .tiocmset = mos7840_tiocmset, | ||
2887 | .attach = mos7840_startup, | ||
2888 | .shutdown = mos7840_shutdown, | ||
2889 | .read_bulk_callback = mos7840_bulk_in_callback, | ||
2890 | .read_int_callback = mos7840_interrupt_callback, | ||
2891 | }; | ||
2892 | |||
2893 | static struct usb_driver io_driver = { | ||
2894 | .name = "mos7840", | ||
2895 | .probe = usb_serial_probe, | ||
2896 | .disconnect = usb_serial_disconnect, | ||
2897 | .id_table = moschip_id_table_combined, | ||
2898 | }; | ||
2899 | |||
2900 | /**************************************************************************** | ||
2901 | * moschip7840_init | ||
2902 | * This is called by the module subsystem, or on startup to initialize us | ||
2903 | ****************************************************************************/ | ||
2904 | static int __init moschip7840_init(void) | ||
2905 | { | ||
2906 | int retval; | ||
2907 | |||
2908 | dbg("%s \n", " mos7840_init :entering.........."); | ||
2909 | |||
2910 | /* Register with the usb serial */ | ||
2911 | retval = usb_serial_register(&moschip7840_4port_device); | ||
2912 | |||
2913 | if (retval) | ||
2914 | goto failed_port_device_register; | ||
2915 | |||
2916 | dbg("%s\n", "Entring..."); | ||
2917 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
2918 | |||
2919 | /* Register with the usb */ | ||
2920 | retval = usb_register(&io_driver); | ||
2921 | |||
2922 | if (retval) | ||
2923 | goto failed_usb_register; | ||
2924 | |||
2925 | if (retval == 0) { | ||
2926 | dbg("%s\n", "Leaving..."); | ||
2927 | return 0; | ||
2928 | } | ||
2929 | |||
2930 | failed_usb_register: | ||
2931 | usb_serial_deregister(&moschip7840_4port_device); | ||
2932 | |||
2933 | failed_port_device_register: | ||
2934 | |||
2935 | return retval; | ||
2936 | } | ||
2937 | |||
2938 | /**************************************************************************** | ||
2939 | * moschip7840_exit | ||
2940 | * Called when the driver is about to be unloaded. | ||
2941 | ****************************************************************************/ | ||
2942 | static void __exit moschip7840_exit(void) | ||
2943 | { | ||
2944 | |||
2945 | dbg("%s \n", " mos7840_exit :entering.........."); | ||
2946 | |||
2947 | usb_deregister(&io_driver); | ||
2948 | |||
2949 | usb_serial_deregister(&moschip7840_4port_device); | ||
2950 | |||
2951 | dbg("%s\n", "Entring..."); | ||
2952 | } | ||
2953 | |||
2954 | module_init(moschip7840_init); | ||
2955 | module_exit(moschip7840_exit); | ||
2956 | |||
2957 | /* Module information */ | ||
2958 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
2959 | MODULE_LICENSE("GPL"); | ||
2960 | |||
2961 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
2962 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 65e4d046951a..1036d436ed23 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -81,10 +81,11 @@ static struct usb_device_id id_table [] = { | |||
81 | { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, | 81 | { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, |
82 | { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, | 82 | { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, |
83 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, | 83 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, |
84 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, | ||
84 | { } /* Terminating entry */ | 85 | { } /* Terminating entry */ |
85 | }; | 86 | }; |
86 | 87 | ||
87 | MODULE_DEVICE_TABLE (usb, id_table); | 88 | MODULE_DEVICE_TABLE(usb, id_table); |
88 | 89 | ||
89 | static struct usb_driver pl2303_driver = { | 90 | static struct usb_driver pl2303_driver = { |
90 | .name = "pl2303", | 91 | .name = "pl2303", |
@@ -127,65 +128,6 @@ static struct usb_driver pl2303_driver = { | |||
127 | #define UART_OVERRUN_ERROR 0x40 | 128 | #define UART_OVERRUN_ERROR 0x40 |
128 | #define UART_CTS 0x80 | 129 | #define UART_CTS 0x80 |
129 | 130 | ||
130 | /* function prototypes for a PL2303 serial converter */ | ||
131 | static int pl2303_open (struct usb_serial_port *port, struct file *filp); | ||
132 | static void pl2303_close (struct usb_serial_port *port, struct file *filp); | ||
133 | static void pl2303_set_termios (struct usb_serial_port *port, | ||
134 | struct termios *old); | ||
135 | static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, | ||
136 | unsigned int cmd, unsigned long arg); | ||
137 | static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs); | ||
138 | static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
139 | static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs); | ||
140 | static int pl2303_write (struct usb_serial_port *port, | ||
141 | const unsigned char *buf, int count); | ||
142 | static void pl2303_send (struct usb_serial_port *port); | ||
143 | static int pl2303_write_room(struct usb_serial_port *port); | ||
144 | static int pl2303_chars_in_buffer(struct usb_serial_port *port); | ||
145 | static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); | ||
146 | static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file); | ||
147 | static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, | ||
148 | unsigned int set, unsigned int clear); | ||
149 | static int pl2303_startup (struct usb_serial *serial); | ||
150 | static void pl2303_shutdown (struct usb_serial *serial); | ||
151 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size); | ||
152 | static void pl2303_buf_free(struct pl2303_buf *pb); | ||
153 | static void pl2303_buf_clear(struct pl2303_buf *pb); | ||
154 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb); | ||
155 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb); | ||
156 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
157 | unsigned int count); | ||
158 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
159 | unsigned int count); | ||
160 | |||
161 | |||
162 | /* All of the device info needed for the PL2303 SIO serial converter */ | ||
163 | static struct usb_serial_driver pl2303_device = { | ||
164 | .driver = { | ||
165 | .owner = THIS_MODULE, | ||
166 | .name = "pl2303", | ||
167 | }, | ||
168 | .id_table = id_table, | ||
169 | .num_interrupt_in = NUM_DONT_CARE, | ||
170 | .num_bulk_in = 1, | ||
171 | .num_bulk_out = 1, | ||
172 | .num_ports = 1, | ||
173 | .open = pl2303_open, | ||
174 | .close = pl2303_close, | ||
175 | .write = pl2303_write, | ||
176 | .ioctl = pl2303_ioctl, | ||
177 | .break_ctl = pl2303_break_ctl, | ||
178 | .set_termios = pl2303_set_termios, | ||
179 | .tiocmget = pl2303_tiocmget, | ||
180 | .tiocmset = pl2303_tiocmset, | ||
181 | .read_bulk_callback = pl2303_read_bulk_callback, | ||
182 | .read_int_callback = pl2303_read_int_callback, | ||
183 | .write_bulk_callback = pl2303_write_bulk_callback, | ||
184 | .write_room = pl2303_write_room, | ||
185 | .chars_in_buffer = pl2303_chars_in_buffer, | ||
186 | .attach = pl2303_startup, | ||
187 | .shutdown = pl2303_shutdown, | ||
188 | }; | ||
189 | 131 | ||
190 | enum pl2303_type { | 132 | enum pl2303_type { |
191 | type_0, /* don't know the difference between type 0 and */ | 133 | type_0, /* don't know the difference between type 0 and */ |
@@ -204,8 +146,166 @@ struct pl2303_private { | |||
204 | enum pl2303_type type; | 146 | enum pl2303_type type; |
205 | }; | 147 | }; |
206 | 148 | ||
149 | /* | ||
150 | * pl2303_buf_alloc | ||
151 | * | ||
152 | * Allocate a circular buffer and all associated memory. | ||
153 | */ | ||
154 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | ||
155 | { | ||
156 | struct pl2303_buf *pb; | ||
157 | |||
158 | if (size == 0) | ||
159 | return NULL; | ||
160 | |||
161 | pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | ||
162 | if (pb == NULL) | ||
163 | return NULL; | ||
164 | |||
165 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
166 | if (pb->buf_buf == NULL) { | ||
167 | kfree(pb); | ||
168 | return NULL; | ||
169 | } | ||
170 | |||
171 | pb->buf_size = size; | ||
172 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
207 | 173 | ||
208 | static int pl2303_startup (struct usb_serial *serial) | 174 | return pb; |
175 | } | ||
176 | |||
177 | /* | ||
178 | * pl2303_buf_free | ||
179 | * | ||
180 | * Free the buffer and all associated memory. | ||
181 | */ | ||
182 | static void pl2303_buf_free(struct pl2303_buf *pb) | ||
183 | { | ||
184 | if (pb) { | ||
185 | kfree(pb->buf_buf); | ||
186 | kfree(pb); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * pl2303_buf_clear | ||
192 | * | ||
193 | * Clear out all data in the circular buffer. | ||
194 | */ | ||
195 | static void pl2303_buf_clear(struct pl2303_buf *pb) | ||
196 | { | ||
197 | if (pb != NULL) | ||
198 | pb->buf_get = pb->buf_put; | ||
199 | /* equivalent to a get of all data available */ | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * pl2303_buf_data_avail | ||
204 | * | ||
205 | * Return the number of bytes of data available in the circular | ||
206 | * buffer. | ||
207 | */ | ||
208 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) | ||
209 | { | ||
210 | if (pb == NULL) | ||
211 | return 0; | ||
212 | |||
213 | return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * pl2303_buf_space_avail | ||
218 | * | ||
219 | * Return the number of bytes of space available in the circular | ||
220 | * buffer. | ||
221 | */ | ||
222 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) | ||
223 | { | ||
224 | if (pb == NULL) | ||
225 | return 0; | ||
226 | |||
227 | return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * pl2303_buf_put | ||
232 | * | ||
233 | * Copy data data from a user buffer and put it into the circular buffer. | ||
234 | * Restrict to the amount of space available. | ||
235 | * | ||
236 | * Return the number of bytes copied. | ||
237 | */ | ||
238 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
239 | unsigned int count) | ||
240 | { | ||
241 | unsigned int len; | ||
242 | |||
243 | if (pb == NULL) | ||
244 | return 0; | ||
245 | |||
246 | len = pl2303_buf_space_avail(pb); | ||
247 | if (count > len) | ||
248 | count = len; | ||
249 | |||
250 | if (count == 0) | ||
251 | return 0; | ||
252 | |||
253 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
254 | if (count > len) { | ||
255 | memcpy(pb->buf_put, buf, len); | ||
256 | memcpy(pb->buf_buf, buf+len, count - len); | ||
257 | pb->buf_put = pb->buf_buf + count - len; | ||
258 | } else { | ||
259 | memcpy(pb->buf_put, buf, count); | ||
260 | if (count < len) | ||
261 | pb->buf_put += count; | ||
262 | else /* count == len */ | ||
263 | pb->buf_put = pb->buf_buf; | ||
264 | } | ||
265 | |||
266 | return count; | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * pl2303_buf_get | ||
271 | * | ||
272 | * Get data from the circular buffer and copy to the given buffer. | ||
273 | * Restrict to the amount of data available. | ||
274 | * | ||
275 | * Return the number of bytes copied. | ||
276 | */ | ||
277 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
278 | unsigned int count) | ||
279 | { | ||
280 | unsigned int len; | ||
281 | |||
282 | if (pb == NULL) | ||
283 | return 0; | ||
284 | |||
285 | len = pl2303_buf_data_avail(pb); | ||
286 | if (count > len) | ||
287 | count = len; | ||
288 | |||
289 | if (count == 0) | ||
290 | return 0; | ||
291 | |||
292 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
293 | if (count > len) { | ||
294 | memcpy(buf, pb->buf_get, len); | ||
295 | memcpy(buf+len, pb->buf_buf, count - len); | ||
296 | pb->buf_get = pb->buf_buf + count - len; | ||
297 | } else { | ||
298 | memcpy(buf, pb->buf_get, count); | ||
299 | if (count < len) | ||
300 | pb->buf_get += count; | ||
301 | else /* count == len */ | ||
302 | pb->buf_get = pb->buf_buf; | ||
303 | } | ||
304 | |||
305 | return count; | ||
306 | } | ||
307 | |||
308 | static int pl2303_startup(struct usb_serial *serial) | ||
209 | { | 309 | { |
210 | struct pl2303_private *priv; | 310 | struct pl2303_private *priv; |
211 | enum pl2303_type type = type_0; | 311 | enum pl2303_type type = type_0; |
@@ -247,36 +347,17 @@ cleanup: | |||
247 | return -ENOMEM; | 347 | return -ENOMEM; |
248 | } | 348 | } |
249 | 349 | ||
250 | static int set_control_lines (struct usb_device *dev, u8 value) | 350 | static int set_control_lines(struct usb_device *dev, u8 value) |
251 | { | 351 | { |
252 | int retval; | 352 | int retval; |
253 | 353 | ||
254 | retval = usb_control_msg (dev, usb_sndctrlpipe (dev, 0), | 354 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
255 | SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, | 355 | SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, |
256 | value, 0, NULL, 0, 100); | 356 | value, 0, NULL, 0, 100); |
257 | dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval); | 357 | dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval); |
258 | return retval; | 358 | return retval; |
259 | } | 359 | } |
260 | 360 | ||
261 | static int pl2303_write (struct usb_serial_port *port, const unsigned char *buf, int count) | ||
262 | { | ||
263 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
264 | unsigned long flags; | ||
265 | |||
266 | dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); | ||
267 | |||
268 | if (!count) | ||
269 | return count; | ||
270 | |||
271 | spin_lock_irqsave(&priv->lock, flags); | ||
272 | count = pl2303_buf_put(priv->buf, buf, count); | ||
273 | spin_unlock_irqrestore(&priv->lock, flags); | ||
274 | |||
275 | pl2303_send(port); | ||
276 | |||
277 | return count; | ||
278 | } | ||
279 | |||
280 | static void pl2303_send(struct usb_serial_port *port) | 361 | static void pl2303_send(struct usb_serial_port *port) |
281 | { | 362 | { |
282 | int count, result; | 363 | int count, result; |
@@ -293,7 +374,7 @@ static void pl2303_send(struct usb_serial_port *port) | |||
293 | } | 374 | } |
294 | 375 | ||
295 | count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, | 376 | count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, |
296 | port->bulk_out_size); | 377 | port->bulk_out_size); |
297 | 378 | ||
298 | if (count == 0) { | 379 | if (count == 0) { |
299 | spin_unlock_irqrestore(&priv->lock, flags); | 380 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -304,13 +385,15 @@ static void pl2303_send(struct usb_serial_port *port) | |||
304 | 385 | ||
305 | spin_unlock_irqrestore(&priv->lock, flags); | 386 | spin_unlock_irqrestore(&priv->lock, flags); |
306 | 387 | ||
307 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); | 388 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, |
389 | port->write_urb->transfer_buffer); | ||
308 | 390 | ||
309 | port->write_urb->transfer_buffer_length = count; | 391 | port->write_urb->transfer_buffer_length = count; |
310 | port->write_urb->dev = port->serial->dev; | 392 | port->write_urb->dev = port->serial->dev; |
311 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); | 393 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
312 | if (result) { | 394 | if (result) { |
313 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | 395 | dev_err(&port->dev, "%s - failed submitting write urb," |
396 | " error %d\n", __FUNCTION__, result); | ||
314 | priv->write_urb_in_use = 0; | 397 | priv->write_urb_in_use = 0; |
315 | // TODO: reschedule pl2303_send | 398 | // TODO: reschedule pl2303_send |
316 | } | 399 | } |
@@ -318,6 +401,26 @@ static void pl2303_send(struct usb_serial_port *port) | |||
318 | usb_serial_port_softint(port); | 401 | usb_serial_port_softint(port); |
319 | } | 402 | } |
320 | 403 | ||
404 | static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf, | ||
405 | int count) | ||
406 | { | ||
407 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
408 | unsigned long flags; | ||
409 | |||
410 | dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); | ||
411 | |||
412 | if (!count) | ||
413 | return count; | ||
414 | |||
415 | spin_lock_irqsave(&priv->lock, flags); | ||
416 | count = pl2303_buf_put(priv->buf, buf, count); | ||
417 | spin_unlock_irqrestore(&priv->lock, flags); | ||
418 | |||
419 | pl2303_send(port); | ||
420 | |||
421 | return count; | ||
422 | } | ||
423 | |||
321 | static int pl2303_write_room(struct usb_serial_port *port) | 424 | static int pl2303_write_room(struct usb_serial_port *port) |
322 | { | 425 | { |
323 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 426 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
@@ -350,7 +453,8 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port) | |||
350 | return chars; | 453 | return chars; |
351 | } | 454 | } |
352 | 455 | ||
353 | static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios) | 456 | static void pl2303_set_termios(struct usb_serial_port *port, |
457 | struct termios *old_termios) | ||
354 | { | 458 | { |
355 | struct usb_serial *serial = port->serial; | 459 | struct usb_serial *serial = port->serial; |
356 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 460 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
@@ -371,7 +475,8 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol | |||
371 | spin_lock_irqsave(&priv->lock, flags); | 475 | spin_lock_irqsave(&priv->lock, flags); |
372 | if (!priv->termios_initialized) { | 476 | if (!priv->termios_initialized) { |
373 | *(port->tty->termios) = tty_std_termios; | 477 | *(port->tty->termios) = tty_std_termios; |
374 | port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 478 | port->tty->termios->c_cflag = B9600 | CS8 | CREAD | |
479 | HUPCL | CLOCAL; | ||
375 | priv->termios_initialized = 1; | 480 | priv->termios_initialized = 1; |
376 | } | 481 | } |
377 | spin_unlock_irqrestore(&priv->lock, flags); | 482 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -380,24 +485,24 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol | |||
380 | /* check that they really want us to change something */ | 485 | /* check that they really want us to change something */ |
381 | if (old_termios) { | 486 | if (old_termios) { |
382 | if ((cflag == old_termios->c_cflag) && | 487 | if ((cflag == old_termios->c_cflag) && |
383 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { | 488 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == |
384 | dbg("%s - nothing to change...", __FUNCTION__); | 489 | RELEVANT_IFLAG(old_termios->c_iflag))) { |
385 | return; | 490 | dbg("%s - nothing to change...", __FUNCTION__); |
491 | return; | ||
386 | } | 492 | } |
387 | } | 493 | } |
388 | 494 | ||
389 | buf = kzalloc (7, GFP_KERNEL); | 495 | buf = kzalloc(7, GFP_KERNEL); |
390 | if (!buf) { | 496 | if (!buf) { |
391 | dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); | 497 | dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); |
392 | return; | 498 | return; |
393 | } | 499 | } |
394 | |||
395 | i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), | ||
396 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, | ||
397 | 0, 0, buf, 7, 100); | ||
398 | dbg ("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, | ||
399 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); | ||
400 | 500 | ||
501 | i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
502 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, | ||
503 | 0, 0, buf, 7, 100); | ||
504 | dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, | ||
505 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); | ||
401 | 506 | ||
402 | if (cflag & CSIZE) { | 507 | if (cflag & CSIZE) { |
403 | switch (cflag & CSIZE) { | 508 | switch (cflag & CSIZE) { |
@@ -429,7 +534,8 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol | |||
429 | case B230400: baud = 230400; break; | 534 | case B230400: baud = 230400; break; |
430 | case B460800: baud = 460800; break; | 535 | case B460800: baud = 460800; break; |
431 | default: | 536 | default: |
432 | dev_err(&port->dev, "pl2303 driver does not support the baudrate requested (fix it)\n"); | 537 | dev_err(&port->dev, "pl2303 driver does not support" |
538 | " the baudrate requested (fix it)\n"); | ||
433 | break; | 539 | break; |
434 | } | 540 | } |
435 | dbg("%s - baud = %d", __FUNCTION__, baud); | 541 | dbg("%s - baud = %d", __FUNCTION__, baud); |
@@ -469,10 +575,10 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol | |||
469 | dbg("%s - parity = none", __FUNCTION__); | 575 | dbg("%s - parity = none", __FUNCTION__); |
470 | } | 576 | } |
471 | 577 | ||
472 | i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), | 578 | i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
473 | SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, | 579 | SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, |
474 | 0, 0, buf, 7, 100); | 580 | 0, 0, buf, 7, 100); |
475 | dbg ("0x21:0x20:0:0 %d", i); | 581 | dbg("0x21:0x20:0:0 %d", i); |
476 | 582 | ||
477 | /* change control lines if we are switching to or from B0 */ | 583 | /* change control lines if we are switching to or from B0 */ |
478 | spin_lock_irqsave(&priv->lock, flags); | 584 | spin_lock_irqsave(&priv->lock, flags); |
@@ -488,13 +594,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol | |||
488 | } else { | 594 | } else { |
489 | spin_unlock_irqrestore(&priv->lock, flags); | 595 | spin_unlock_irqrestore(&priv->lock, flags); |
490 | } | 596 | } |
491 | 597 | ||
492 | buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; | 598 | buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; |
493 | 599 | ||
494 | i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), | 600 | i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
495 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, | 601 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, |
496 | 0, 0, buf, 7, 100); | 602 | 0, 0, buf, 7, 100); |
497 | dbg ("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, | 603 | dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, |
498 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); | 604 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); |
499 | 605 | ||
500 | if (cflag & CRTSCTS) { | 606 | if (cflag & CRTSCTS) { |
@@ -503,18 +609,82 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol | |||
503 | index = 0x61; | 609 | index = 0x61; |
504 | else | 610 | else |
505 | index = 0x41; | 611 | index = 0x41; |
506 | i = usb_control_msg(serial->dev, | 612 | i = usb_control_msg(serial->dev, |
507 | usb_sndctrlpipe(serial->dev, 0), | 613 | usb_sndctrlpipe(serial->dev, 0), |
508 | VENDOR_WRITE_REQUEST, | 614 | VENDOR_WRITE_REQUEST, |
509 | VENDOR_WRITE_REQUEST_TYPE, | 615 | VENDOR_WRITE_REQUEST_TYPE, |
510 | 0x0, index, NULL, 0, 100); | 616 | 0x0, index, NULL, 0, 100); |
511 | dbg ("0x40:0x1:0x0:0x%x %d", index, i); | 617 | dbg("0x40:0x1:0x0:0x%x %d", index, i); |
618 | } | ||
619 | |||
620 | kfree(buf); | ||
621 | } | ||
622 | |||
623 | static void pl2303_close(struct usb_serial_port *port, struct file *filp) | ||
624 | { | ||
625 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
626 | unsigned long flags; | ||
627 | unsigned int c_cflag; | ||
628 | int bps; | ||
629 | long timeout; | ||
630 | wait_queue_t wait; | ||
631 | |||
632 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
633 | |||
634 | /* wait for data to drain from the buffer */ | ||
635 | spin_lock_irqsave(&priv->lock, flags); | ||
636 | timeout = PL2303_CLOSING_WAIT; | ||
637 | init_waitqueue_entry(&wait, current); | ||
638 | add_wait_queue(&port->tty->write_wait, &wait); | ||
639 | for (;;) { | ||
640 | set_current_state(TASK_INTERRUPTIBLE); | ||
641 | if (pl2303_buf_data_avail(priv->buf) == 0 || | ||
642 | timeout == 0 || signal_pending(current) || | ||
643 | !usb_get_intfdata(port->serial->interface)) /* disconnect */ | ||
644 | break; | ||
645 | spin_unlock_irqrestore(&priv->lock, flags); | ||
646 | timeout = schedule_timeout(timeout); | ||
647 | spin_lock_irqsave(&priv->lock, flags); | ||
512 | } | 648 | } |
649 | set_current_state(TASK_RUNNING); | ||
650 | remove_wait_queue(&port->tty->write_wait, &wait); | ||
651 | /* clear out any remaining data in the buffer */ | ||
652 | pl2303_buf_clear(priv->buf); | ||
653 | spin_unlock_irqrestore(&priv->lock, flags); | ||
654 | |||
655 | /* wait for characters to drain from the device */ | ||
656 | /* (this is long enough for the entire 256 byte */ | ||
657 | /* pl2303 hardware buffer to drain with no flow */ | ||
658 | /* control for data rates of 1200 bps or more, */ | ||
659 | /* for lower rates we should really know how much */ | ||
660 | /* data is in the buffer to compute a delay */ | ||
661 | /* that is not unnecessarily long) */ | ||
662 | bps = tty_get_baud_rate(port->tty); | ||
663 | if (bps > 1200) | ||
664 | timeout = max((HZ*2560)/bps,HZ/10); | ||
665 | else | ||
666 | timeout = 2*HZ; | ||
667 | schedule_timeout_interruptible(timeout); | ||
513 | 668 | ||
514 | kfree (buf); | 669 | /* shutdown our urbs */ |
670 | dbg("%s - shutting down urbs", __FUNCTION__); | ||
671 | usb_kill_urb(port->write_urb); | ||
672 | usb_kill_urb(port->read_urb); | ||
673 | usb_kill_urb(port->interrupt_in_urb); | ||
674 | |||
675 | if (port->tty) { | ||
676 | c_cflag = port->tty->termios->c_cflag; | ||
677 | if (c_cflag & HUPCL) { | ||
678 | /* drop DTR and RTS */ | ||
679 | spin_lock_irqsave(&priv->lock, flags); | ||
680 | priv->line_control = 0; | ||
681 | spin_unlock_irqrestore(&priv->lock, flags); | ||
682 | set_control_lines(port->serial->dev, 0); | ||
683 | } | ||
684 | } | ||
515 | } | 685 | } |
516 | 686 | ||
517 | static int pl2303_open (struct usb_serial_port *port, struct file *filp) | 687 | static int pl2303_open(struct usb_serial_port *port, struct file *filp) |
518 | { | 688 | { |
519 | struct termios tmp_termios; | 689 | struct termios tmp_termios; |
520 | struct usb_serial *serial = port->serial; | 690 | struct usb_serial *serial = port->serial; |
@@ -568,98 +738,35 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp) | |||
568 | 738 | ||
569 | /* Setup termios */ | 739 | /* Setup termios */ |
570 | if (port->tty) { | 740 | if (port->tty) { |
571 | pl2303_set_termios (port, &tmp_termios); | 741 | pl2303_set_termios(port, &tmp_termios); |
572 | } | 742 | } |
573 | 743 | ||
574 | //FIXME: need to assert RTS and DTR if CRTSCTS off | 744 | //FIXME: need to assert RTS and DTR if CRTSCTS off |
575 | 745 | ||
576 | dbg("%s - submitting read urb", __FUNCTION__); | 746 | dbg("%s - submitting read urb", __FUNCTION__); |
577 | port->read_urb->dev = serial->dev; | 747 | port->read_urb->dev = serial->dev; |
578 | result = usb_submit_urb (port->read_urb, GFP_KERNEL); | 748 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); |
579 | if (result) { | 749 | if (result) { |
580 | dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result); | 750 | dev_err(&port->dev, "%s - failed submitting read urb," |
581 | pl2303_close (port, NULL); | 751 | " error %d\n", __FUNCTION__, result); |
752 | pl2303_close(port, NULL); | ||
582 | return -EPROTO; | 753 | return -EPROTO; |
583 | } | 754 | } |
584 | 755 | ||
585 | dbg("%s - submitting interrupt urb", __FUNCTION__); | 756 | dbg("%s - submitting interrupt urb", __FUNCTION__); |
586 | port->interrupt_in_urb->dev = serial->dev; | 757 | port->interrupt_in_urb->dev = serial->dev; |
587 | result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL); | 758 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
588 | if (result) { | 759 | if (result) { |
589 | dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n", __FUNCTION__, result); | 760 | dev_err(&port->dev, "%s - failed submitting interrupt urb," |
590 | pl2303_close (port, NULL); | 761 | " error %d\n", __FUNCTION__, result); |
762 | pl2303_close(port, NULL); | ||
591 | return -EPROTO; | 763 | return -EPROTO; |
592 | } | 764 | } |
593 | return 0; | 765 | return 0; |
594 | } | 766 | } |
595 | 767 | ||
596 | 768 | static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file, | |
597 | static void pl2303_close (struct usb_serial_port *port, struct file *filp) | 769 | unsigned int set, unsigned int clear) |
598 | { | ||
599 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
600 | unsigned long flags; | ||
601 | unsigned int c_cflag; | ||
602 | int bps; | ||
603 | long timeout; | ||
604 | wait_queue_t wait; | ||
605 | |||
606 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
607 | |||
608 | /* wait for data to drain from the buffer */ | ||
609 | spin_lock_irqsave(&priv->lock, flags); | ||
610 | timeout = PL2303_CLOSING_WAIT; | ||
611 | init_waitqueue_entry(&wait, current); | ||
612 | add_wait_queue(&port->tty->write_wait, &wait); | ||
613 | for (;;) { | ||
614 | set_current_state(TASK_INTERRUPTIBLE); | ||
615 | if (pl2303_buf_data_avail(priv->buf) == 0 | ||
616 | || timeout == 0 || signal_pending(current) | ||
617 | || !usb_get_intfdata(port->serial->interface)) /* disconnect */ | ||
618 | break; | ||
619 | spin_unlock_irqrestore(&priv->lock, flags); | ||
620 | timeout = schedule_timeout(timeout); | ||
621 | spin_lock_irqsave(&priv->lock, flags); | ||
622 | } | ||
623 | set_current_state(TASK_RUNNING); | ||
624 | remove_wait_queue(&port->tty->write_wait, &wait); | ||
625 | /* clear out any remaining data in the buffer */ | ||
626 | pl2303_buf_clear(priv->buf); | ||
627 | spin_unlock_irqrestore(&priv->lock, flags); | ||
628 | |||
629 | /* wait for characters to drain from the device */ | ||
630 | /* (this is long enough for the entire 256 byte */ | ||
631 | /* pl2303 hardware buffer to drain with no flow */ | ||
632 | /* control for data rates of 1200 bps or more, */ | ||
633 | /* for lower rates we should really know how much */ | ||
634 | /* data is in the buffer to compute a delay */ | ||
635 | /* that is not unnecessarily long) */ | ||
636 | bps = tty_get_baud_rate(port->tty); | ||
637 | if (bps > 1200) | ||
638 | timeout = max((HZ*2560)/bps,HZ/10); | ||
639 | else | ||
640 | timeout = 2*HZ; | ||
641 | schedule_timeout_interruptible(timeout); | ||
642 | |||
643 | /* shutdown our urbs */ | ||
644 | dbg("%s - shutting down urbs", __FUNCTION__); | ||
645 | usb_kill_urb(port->write_urb); | ||
646 | usb_kill_urb(port->read_urb); | ||
647 | usb_kill_urb(port->interrupt_in_urb); | ||
648 | |||
649 | if (port->tty) { | ||
650 | c_cflag = port->tty->termios->c_cflag; | ||
651 | if (c_cflag & HUPCL) { | ||
652 | /* drop DTR and RTS */ | ||
653 | spin_lock_irqsave(&priv->lock, flags); | ||
654 | priv->line_control = 0; | ||
655 | spin_unlock_irqrestore (&priv->lock, flags); | ||
656 | set_control_lines (port->serial->dev, 0); | ||
657 | } | ||
658 | } | ||
659 | } | ||
660 | |||
661 | static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, | ||
662 | unsigned int set, unsigned int clear) | ||
663 | { | 770 | { |
664 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 771 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
665 | unsigned long flags; | 772 | unsigned long flags; |
@@ -668,7 +775,7 @@ static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, | |||
668 | if (!usb_get_intfdata(port->serial->interface)) | 775 | if (!usb_get_intfdata(port->serial->interface)) |
669 | return -ENODEV; | 776 | return -ENODEV; |
670 | 777 | ||
671 | spin_lock_irqsave (&priv->lock, flags); | 778 | spin_lock_irqsave(&priv->lock, flags); |
672 | if (set & TIOCM_RTS) | 779 | if (set & TIOCM_RTS) |
673 | priv->line_control |= CONTROL_RTS; | 780 | priv->line_control |= CONTROL_RTS; |
674 | if (set & TIOCM_DTR) | 781 | if (set & TIOCM_DTR) |
@@ -678,12 +785,12 @@ static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, | |||
678 | if (clear & TIOCM_DTR) | 785 | if (clear & TIOCM_DTR) |
679 | priv->line_control &= ~CONTROL_DTR; | 786 | priv->line_control &= ~CONTROL_DTR; |
680 | control = priv->line_control; | 787 | control = priv->line_control; |
681 | spin_unlock_irqrestore (&priv->lock, flags); | 788 | spin_unlock_irqrestore(&priv->lock, flags); |
682 | 789 | ||
683 | return set_control_lines (port->serial->dev, control); | 790 | return set_control_lines(port->serial->dev, control); |
684 | } | 791 | } |
685 | 792 | ||
686 | static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file) | 793 | static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file) |
687 | { | 794 | { |
688 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 795 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
689 | unsigned long flags; | 796 | unsigned long flags; |
@@ -696,10 +803,10 @@ static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file) | |||
696 | if (!usb_get_intfdata(port->serial->interface)) | 803 | if (!usb_get_intfdata(port->serial->interface)) |
697 | return -ENODEV; | 804 | return -ENODEV; |
698 | 805 | ||
699 | spin_lock_irqsave (&priv->lock, flags); | 806 | spin_lock_irqsave(&priv->lock, flags); |
700 | mcr = priv->line_control; | 807 | mcr = priv->line_control; |
701 | status = priv->line_status; | 808 | status = priv->line_status; |
702 | spin_unlock_irqrestore (&priv->lock, flags); | 809 | spin_unlock_irqrestore(&priv->lock, flags); |
703 | 810 | ||
704 | result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) | 811 | result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) |
705 | | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) | 812 | | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) |
@@ -721,22 +828,22 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
721 | unsigned int status; | 828 | unsigned int status; |
722 | unsigned int changed; | 829 | unsigned int changed; |
723 | 830 | ||
724 | spin_lock_irqsave (&priv->lock, flags); | 831 | spin_lock_irqsave(&priv->lock, flags); |
725 | prevstatus = priv->line_status; | 832 | prevstatus = priv->line_status; |
726 | spin_unlock_irqrestore (&priv->lock, flags); | 833 | spin_unlock_irqrestore(&priv->lock, flags); |
727 | 834 | ||
728 | while (1) { | 835 | while (1) { |
729 | interruptible_sleep_on(&priv->delta_msr_wait); | 836 | interruptible_sleep_on(&priv->delta_msr_wait); |
730 | /* see if a signal did it */ | 837 | /* see if a signal did it */ |
731 | if (signal_pending(current)) | 838 | if (signal_pending(current)) |
732 | return -ERESTARTSYS; | 839 | return -ERESTARTSYS; |
733 | 840 | ||
734 | spin_lock_irqsave (&priv->lock, flags); | 841 | spin_lock_irqsave(&priv->lock, flags); |
735 | status = priv->line_status; | 842 | status = priv->line_status; |
736 | spin_unlock_irqrestore (&priv->lock, flags); | 843 | spin_unlock_irqrestore(&priv->lock, flags); |
737 | 844 | ||
738 | changed=prevstatus^status; | 845 | changed=prevstatus^status; |
739 | 846 | ||
740 | if (((arg & TIOCM_RNG) && (changed & UART_RING)) || | 847 | if (((arg & TIOCM_RNG) && (changed & UART_RING)) || |
741 | ((arg & TIOCM_DSR) && (changed & UART_DSR)) || | 848 | ((arg & TIOCM_DSR) && (changed & UART_DSR)) || |
742 | ((arg & TIOCM_CD) && (changed & UART_DCD)) || | 849 | ((arg & TIOCM_CD) && (changed & UART_DCD)) || |
@@ -749,7 +856,8 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
749 | return 0; | 856 | return 0; |
750 | } | 857 | } |
751 | 858 | ||
752 | static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) | 859 | static int pl2303_ioctl(struct usb_serial_port *port, struct file *file, |
860 | unsigned int cmd, unsigned long arg) | ||
753 | { | 861 | { |
754 | dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); | 862 | dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); |
755 | 863 | ||
@@ -766,7 +874,7 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsign | |||
766 | return -ENOIOCTLCMD; | 874 | return -ENOIOCTLCMD; |
767 | } | 875 | } |
768 | 876 | ||
769 | static void pl2303_break_ctl (struct usb_serial_port *port, int break_state) | 877 | static void pl2303_break_ctl(struct usb_serial_port *port, int break_state) |
770 | { | 878 | { |
771 | struct usb_serial *serial = port->serial; | 879 | struct usb_serial *serial = port->serial; |
772 | u16 state; | 880 | u16 state; |
@@ -780,15 +888,14 @@ static void pl2303_break_ctl (struct usb_serial_port *port, int break_state) | |||
780 | state = BREAK_ON; | 888 | state = BREAK_ON; |
781 | dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on"); | 889 | dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on"); |
782 | 890 | ||
783 | result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), | 891 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
784 | BREAK_REQUEST, BREAK_REQUEST_TYPE, state, | 892 | BREAK_REQUEST, BREAK_REQUEST_TYPE, state, |
785 | 0, NULL, 0, 100); | 893 | 0, NULL, 0, 100); |
786 | if (result) | 894 | if (result) |
787 | dbg("%s - error sending break = %d", __FUNCTION__, result); | 895 | dbg("%s - error sending break = %d", __FUNCTION__, result); |
788 | } | 896 | } |
789 | 897 | ||
790 | 898 | static void pl2303_shutdown(struct usb_serial *serial) | |
791 | static void pl2303_shutdown (struct usb_serial *serial) | ||
792 | { | 899 | { |
793 | int i; | 900 | int i; |
794 | struct pl2303_private *priv; | 901 | struct pl2303_private *priv; |
@@ -802,7 +909,7 @@ static void pl2303_shutdown (struct usb_serial *serial) | |||
802 | kfree(priv); | 909 | kfree(priv); |
803 | usb_set_serial_port_data(serial->port[i], NULL); | 910 | usb_set_serial_port_data(serial->port[i], NULL); |
804 | } | 911 | } |
805 | } | 912 | } |
806 | } | 913 | } |
807 | 914 | ||
808 | static void pl2303_update_line_status(struct usb_serial_port *port, | 915 | static void pl2303_update_line_status(struct usb_serial_port *port, |
@@ -814,29 +921,33 @@ static void pl2303_update_line_status(struct usb_serial_port *port, | |||
814 | unsigned long flags; | 921 | unsigned long flags; |
815 | u8 status_idx = UART_STATE; | 922 | u8 status_idx = UART_STATE; |
816 | u8 length = UART_STATE + 1; | 923 | u8 length = UART_STATE + 1; |
924 | u16 idv, idp; | ||
925 | |||
926 | idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); | ||
927 | idp = le16_to_cpu(port->serial->dev->descriptor.idProduct); | ||
817 | 928 | ||
818 | if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && | 929 | |
819 | (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 || | 930 | if (idv == SIEMENS_VENDOR_ID) { |
820 | le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_SX1 || | 931 | if (idp == SIEMENS_PRODUCT_ID_X65 || |
821 | le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X75)) { | 932 | idp == SIEMENS_PRODUCT_ID_SX1 || |
822 | length = 1; | 933 | idp == SIEMENS_PRODUCT_ID_X75) { |
823 | status_idx = 0; | 934 | |
935 | length = 1; | ||
936 | status_idx = 0; | ||
937 | } | ||
824 | } | 938 | } |
825 | 939 | ||
826 | if (actual_length < length) | 940 | if (actual_length < length) |
827 | goto exit; | 941 | return; |
828 | 942 | ||
829 | /* Save off the uart status for others to look at */ | 943 | /* Save off the uart status for others to look at */ |
830 | spin_lock_irqsave(&priv->lock, flags); | 944 | spin_lock_irqsave(&priv->lock, flags); |
831 | priv->line_status = data[status_idx]; | 945 | priv->line_status = data[status_idx]; |
832 | spin_unlock_irqrestore(&priv->lock, flags); | 946 | spin_unlock_irqrestore(&priv->lock, flags); |
833 | wake_up_interruptible (&priv->delta_msr_wait); | 947 | wake_up_interruptible(&priv->delta_msr_wait); |
834 | |||
835 | exit: | ||
836 | return; | ||
837 | } | 948 | } |
838 | 949 | ||
839 | static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs) | 950 | static void pl2303_read_int_callback(struct urb *urb, struct pt_regs *regs) |
840 | { | 951 | { |
841 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 952 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
842 | unsigned char *data = urb->transfer_buffer; | 953 | unsigned char *data = urb->transfer_buffer; |
@@ -853,25 +964,29 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs) | |||
853 | case -ENOENT: | 964 | case -ENOENT: |
854 | case -ESHUTDOWN: | 965 | case -ESHUTDOWN: |
855 | /* this urb is terminated, clean up */ | 966 | /* this urb is terminated, clean up */ |
856 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 967 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, |
968 | urb->status); | ||
857 | return; | 969 | return; |
858 | default: | 970 | default: |
859 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 971 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, |
972 | urb->status); | ||
860 | goto exit; | 973 | goto exit; |
861 | } | 974 | } |
862 | 975 | ||
863 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer); | 976 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, |
977 | urb->actual_length, urb->transfer_buffer); | ||
978 | |||
864 | pl2303_update_line_status(port, data, actual_length); | 979 | pl2303_update_line_status(port, data, actual_length); |
865 | 980 | ||
866 | exit: | 981 | exit: |
867 | status = usb_submit_urb (urb, GFP_ATOMIC); | 982 | status = usb_submit_urb(urb, GFP_ATOMIC); |
868 | if (status) | 983 | if (status) |
869 | dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", | 984 | dev_err(&urb->dev->dev, |
985 | "%s - usb_submit_urb failed with result %d\n", | ||
870 | __FUNCTION__, status); | 986 | __FUNCTION__, status); |
871 | } | 987 | } |
872 | 988 | ||
873 | 989 | static void pl2303_read_bulk_callback(struct urb *urb, struct pt_regs *regs) | |
874 | static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | ||
875 | { | 990 | { |
876 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 991 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
877 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 992 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
@@ -892,20 +1007,25 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
892 | return; | 1007 | return; |
893 | } | 1008 | } |
894 | if (urb->status == -EPROTO) { | 1009 | if (urb->status == -EPROTO) { |
895 | /* PL2303 mysteriously fails with -EPROTO reschedule the read */ | 1010 | /* PL2303 mysteriously fails with -EPROTO reschedule |
896 | dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__); | 1011 | * the read */ |
1012 | dbg("%s - caught -EPROTO, resubmitting the urb", | ||
1013 | __FUNCTION__); | ||
897 | urb->status = 0; | 1014 | urb->status = 0; |
898 | urb->dev = port->serial->dev; | 1015 | urb->dev = port->serial->dev; |
899 | result = usb_submit_urb(urb, GFP_ATOMIC); | 1016 | result = usb_submit_urb(urb, GFP_ATOMIC); |
900 | if (result) | 1017 | if (result) |
901 | dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | 1018 | dev_err(&urb->dev->dev, "%s - failed" |
1019 | " resubmitting read urb, error %d\n", | ||
1020 | __FUNCTION__, result); | ||
902 | return; | 1021 | return; |
903 | } | 1022 | } |
904 | dbg("%s - unable to handle the error, exiting.", __FUNCTION__); | 1023 | dbg("%s - unable to handle the error, exiting.", __FUNCTION__); |
905 | return; | 1024 | return; |
906 | } | 1025 | } |
907 | 1026 | ||
908 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 1027 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, |
1028 | urb->actual_length, data); | ||
909 | 1029 | ||
910 | /* get tty_flag from status */ | 1030 | /* get tty_flag from status */ |
911 | tty_flag = TTY_NORMAL; | 1031 | tty_flag = TTY_NORMAL; |
@@ -914,7 +1034,7 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
914 | status = priv->line_status; | 1034 | status = priv->line_status; |
915 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; | 1035 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; |
916 | spin_unlock_irqrestore(&priv->lock, flags); | 1036 | spin_unlock_irqrestore(&priv->lock, flags); |
917 | wake_up_interruptible (&priv->delta_msr_wait); | 1037 | wake_up_interruptible(&priv->delta_msr_wait); |
918 | 1038 | ||
919 | /* break takes precedence over parity, */ | 1039 | /* break takes precedence over parity, */ |
920 | /* which takes precedence over framing errors */ | 1040 | /* which takes precedence over framing errors */ |
@@ -933,8 +1053,8 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
933 | if (status & UART_OVERRUN_ERROR) | 1053 | if (status & UART_OVERRUN_ERROR) |
934 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 1054 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
935 | for (i = 0; i < urb->actual_length; ++i) | 1055 | for (i = 0; i < urb->actual_length; ++i) |
936 | tty_insert_flip_char (tty, data[i], tty_flag); | 1056 | tty_insert_flip_char(tty, data[i], tty_flag); |
937 | tty_flip_buffer_push (tty); | 1057 | tty_flip_buffer_push(tty); |
938 | } | 1058 | } |
939 | 1059 | ||
940 | /* Schedule the next read _if_ we are still open */ | 1060 | /* Schedule the next read _if_ we are still open */ |
@@ -942,15 +1062,14 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
942 | urb->dev = port->serial->dev; | 1062 | urb->dev = port->serial->dev; |
943 | result = usb_submit_urb(urb, GFP_ATOMIC); | 1063 | result = usb_submit_urb(urb, GFP_ATOMIC); |
944 | if (result) | 1064 | if (result) |
945 | dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | 1065 | dev_err(&urb->dev->dev, "%s - failed resubmitting" |
1066 | " read urb, error %d\n", __FUNCTION__, result); | ||
946 | } | 1067 | } |
947 | 1068 | ||
948 | return; | 1069 | return; |
949 | } | 1070 | } |
950 | 1071 | ||
951 | 1072 | static void pl2303_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |
952 | |||
953 | static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | ||
954 | { | 1073 | { |
955 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 1074 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
956 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 1075 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
@@ -966,18 +1085,21 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
966 | case -ENOENT: | 1085 | case -ENOENT: |
967 | case -ESHUTDOWN: | 1086 | case -ESHUTDOWN: |
968 | /* this urb is terminated, clean up */ | 1087 | /* this urb is terminated, clean up */ |
969 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 1088 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, |
1089 | urb->status); | ||
970 | priv->write_urb_in_use = 0; | 1090 | priv->write_urb_in_use = 0; |
971 | return; | 1091 | return; |
972 | default: | 1092 | default: |
973 | /* error in the urb, so we have to resubmit it */ | 1093 | /* error in the urb, so we have to resubmit it */ |
974 | dbg("%s - Overflow in write", __FUNCTION__); | 1094 | dbg("%s - Overflow in write", __FUNCTION__); |
975 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 1095 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, |
1096 | urb->status); | ||
976 | port->write_urb->transfer_buffer_length = 1; | 1097 | port->write_urb->transfer_buffer_length = 1; |
977 | port->write_urb->dev = port->serial->dev; | 1098 | port->write_urb->dev = port->serial->dev; |
978 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); | 1099 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
979 | if (result) | 1100 | if (result) |
980 | dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result); | 1101 | dev_err(&urb->dev->dev, "%s - failed resubmitting write" |
1102 | " urb, error %d\n", __FUNCTION__, result); | ||
981 | else | 1103 | else |
982 | return; | 1104 | return; |
983 | } | 1105 | } |
@@ -988,191 +1110,38 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
988 | pl2303_send(port); | 1110 | pl2303_send(port); |
989 | } | 1111 | } |
990 | 1112 | ||
1113 | /* All of the device info needed for the PL2303 SIO serial converter */ | ||
1114 | static struct usb_serial_driver pl2303_device = { | ||
1115 | .driver = { | ||
1116 | .owner = THIS_MODULE, | ||
1117 | .name = "pl2303", | ||
1118 | }, | ||
1119 | .id_table = id_table, | ||
1120 | .num_interrupt_in = NUM_DONT_CARE, | ||
1121 | .num_bulk_in = 1, | ||
1122 | .num_bulk_out = 1, | ||
1123 | .num_ports = 1, | ||
1124 | .open = pl2303_open, | ||
1125 | .close = pl2303_close, | ||
1126 | .write = pl2303_write, | ||
1127 | .ioctl = pl2303_ioctl, | ||
1128 | .break_ctl = pl2303_break_ctl, | ||
1129 | .set_termios = pl2303_set_termios, | ||
1130 | .tiocmget = pl2303_tiocmget, | ||
1131 | .tiocmset = pl2303_tiocmset, | ||
1132 | .read_bulk_callback = pl2303_read_bulk_callback, | ||
1133 | .read_int_callback = pl2303_read_int_callback, | ||
1134 | .write_bulk_callback = pl2303_write_bulk_callback, | ||
1135 | .write_room = pl2303_write_room, | ||
1136 | .chars_in_buffer = pl2303_chars_in_buffer, | ||
1137 | .attach = pl2303_startup, | ||
1138 | .shutdown = pl2303_shutdown, | ||
1139 | }; | ||
991 | 1140 | ||
992 | /* | 1141 | static int __init pl2303_init(void) |
993 | * pl2303_buf_alloc | ||
994 | * | ||
995 | * Allocate a circular buffer and all associated memory. | ||
996 | */ | ||
997 | |||
998 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | ||
999 | { | ||
1000 | |||
1001 | struct pl2303_buf *pb; | ||
1002 | |||
1003 | |||
1004 | if (size == 0) | ||
1005 | return NULL; | ||
1006 | |||
1007 | pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | ||
1008 | if (pb == NULL) | ||
1009 | return NULL; | ||
1010 | |||
1011 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
1012 | if (pb->buf_buf == NULL) { | ||
1013 | kfree(pb); | ||
1014 | return NULL; | ||
1015 | } | ||
1016 | |||
1017 | pb->buf_size = size; | ||
1018 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
1019 | |||
1020 | return pb; | ||
1021 | |||
1022 | } | ||
1023 | |||
1024 | |||
1025 | /* | ||
1026 | * pl2303_buf_free | ||
1027 | * | ||
1028 | * Free the buffer and all associated memory. | ||
1029 | */ | ||
1030 | |||
1031 | static void pl2303_buf_free(struct pl2303_buf *pb) | ||
1032 | { | ||
1033 | if (pb) { | ||
1034 | kfree(pb->buf_buf); | ||
1035 | kfree(pb); | ||
1036 | } | ||
1037 | } | ||
1038 | |||
1039 | |||
1040 | /* | ||
1041 | * pl2303_buf_clear | ||
1042 | * | ||
1043 | * Clear out all data in the circular buffer. | ||
1044 | */ | ||
1045 | |||
1046 | static void pl2303_buf_clear(struct pl2303_buf *pb) | ||
1047 | { | ||
1048 | if (pb != NULL) | ||
1049 | pb->buf_get = pb->buf_put; | ||
1050 | /* equivalent to a get of all data available */ | ||
1051 | } | ||
1052 | |||
1053 | |||
1054 | /* | ||
1055 | * pl2303_buf_data_avail | ||
1056 | * | ||
1057 | * Return the number of bytes of data available in the circular | ||
1058 | * buffer. | ||
1059 | */ | ||
1060 | |||
1061 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) | ||
1062 | { | ||
1063 | if (pb != NULL) | ||
1064 | return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); | ||
1065 | else | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | /* | ||
1071 | * pl2303_buf_space_avail | ||
1072 | * | ||
1073 | * Return the number of bytes of space available in the circular | ||
1074 | * buffer. | ||
1075 | */ | ||
1076 | |||
1077 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) | ||
1078 | { | ||
1079 | if (pb != NULL) | ||
1080 | return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); | ||
1081 | else | ||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | |||
1086 | /* | ||
1087 | * pl2303_buf_put | ||
1088 | * | ||
1089 | * Copy data data from a user buffer and put it into the circular buffer. | ||
1090 | * Restrict to the amount of space available. | ||
1091 | * | ||
1092 | * Return the number of bytes copied. | ||
1093 | */ | ||
1094 | |||
1095 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
1096 | unsigned int count) | ||
1097 | { | ||
1098 | |||
1099 | unsigned int len; | ||
1100 | |||
1101 | |||
1102 | if (pb == NULL) | ||
1103 | return 0; | ||
1104 | |||
1105 | len = pl2303_buf_space_avail(pb); | ||
1106 | if (count > len) | ||
1107 | count = len; | ||
1108 | |||
1109 | if (count == 0) | ||
1110 | return 0; | ||
1111 | |||
1112 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
1113 | if (count > len) { | ||
1114 | memcpy(pb->buf_put, buf, len); | ||
1115 | memcpy(pb->buf_buf, buf+len, count - len); | ||
1116 | pb->buf_put = pb->buf_buf + count - len; | ||
1117 | } else { | ||
1118 | memcpy(pb->buf_put, buf, count); | ||
1119 | if (count < len) | ||
1120 | pb->buf_put += count; | ||
1121 | else /* count == len */ | ||
1122 | pb->buf_put = pb->buf_buf; | ||
1123 | } | ||
1124 | |||
1125 | return count; | ||
1126 | |||
1127 | } | ||
1128 | |||
1129 | |||
1130 | /* | ||
1131 | * pl2303_buf_get | ||
1132 | * | ||
1133 | * Get data from the circular buffer and copy to the given buffer. | ||
1134 | * Restrict to the amount of data available. | ||
1135 | * | ||
1136 | * Return the number of bytes copied. | ||
1137 | */ | ||
1138 | |||
1139 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
1140 | unsigned int count) | ||
1141 | { | ||
1142 | |||
1143 | unsigned int len; | ||
1144 | |||
1145 | |||
1146 | if (pb == NULL) | ||
1147 | return 0; | ||
1148 | |||
1149 | len = pl2303_buf_data_avail(pb); | ||
1150 | if (count > len) | ||
1151 | count = len; | ||
1152 | |||
1153 | if (count == 0) | ||
1154 | return 0; | ||
1155 | |||
1156 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
1157 | if (count > len) { | ||
1158 | memcpy(buf, pb->buf_get, len); | ||
1159 | memcpy(buf+len, pb->buf_buf, count - len); | ||
1160 | pb->buf_get = pb->buf_buf + count - len; | ||
1161 | } else { | ||
1162 | memcpy(buf, pb->buf_get, count); | ||
1163 | if (count < len) | ||
1164 | pb->buf_get += count; | ||
1165 | else /* count == len */ | ||
1166 | pb->buf_get = pb->buf_buf; | ||
1167 | } | ||
1168 | |||
1169 | return count; | ||
1170 | |||
1171 | } | ||
1172 | |||
1173 | static int __init pl2303_init (void) | ||
1174 | { | 1142 | { |
1175 | int retval; | 1143 | int retval; |
1144 | |||
1176 | retval = usb_serial_register(&pl2303_device); | 1145 | retval = usb_serial_register(&pl2303_device); |
1177 | if (retval) | 1146 | if (retval) |
1178 | goto failed_usb_serial_register; | 1147 | goto failed_usb_serial_register; |
@@ -1187,14 +1156,12 @@ failed_usb_serial_register: | |||
1187 | return retval; | 1156 | return retval; |
1188 | } | 1157 | } |
1189 | 1158 | ||
1190 | 1159 | static void __exit pl2303_exit(void) | |
1191 | static void __exit pl2303_exit (void) | ||
1192 | { | 1160 | { |
1193 | usb_deregister (&pl2303_driver); | 1161 | usb_deregister(&pl2303_driver); |
1194 | usb_serial_deregister (&pl2303_device); | 1162 | usb_serial_deregister(&pl2303_device); |
1195 | } | 1163 | } |
1196 | 1164 | ||
1197 | |||
1198 | module_init(pl2303_init); | 1165 | module_init(pl2303_init); |
1199 | module_exit(pl2303_exit); | 1166 | module_exit(pl2303_exit); |
1200 | 1167 | ||
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 55195e76eb6f..762cc290ef58 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -89,3 +89,7 @@ | |||
89 | /* Belkin "F5U257" Serial Adapter */ | 89 | /* Belkin "F5U257" Serial Adapter */ |
90 | #define BELKIN_VENDOR_ID 0x050d | 90 | #define BELKIN_VENDOR_ID 0x050d |
91 | #define BELKIN_PRODUCT_ID 0x0257 | 91 | #define BELKIN_PRODUCT_ID 0x0257 |
92 | |||
93 | /* Alcor Micro Corp. USB 2.0 TO RS-232 */ | ||
94 | #define ALCOR_VENDOR_ID 0x058F | ||
95 | #define ALCOR_PRODUCT_ID 0x9720 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index e06a41bd0f3b..0222d92842b8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -676,33 +676,29 @@ int usb_serial_probe(struct usb_interface *interface, | |||
676 | iface_desc = interface->cur_altsetting; | 676 | iface_desc = interface->cur_altsetting; |
677 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 677 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
678 | endpoint = &iface_desc->endpoint[i].desc; | 678 | endpoint = &iface_desc->endpoint[i].desc; |
679 | 679 | ||
680 | if ((endpoint->bEndpointAddress & 0x80) && | 680 | if (usb_endpoint_is_bulk_in(endpoint)) { |
681 | ((endpoint->bmAttributes & 3) == 0x02)) { | ||
682 | /* we found a bulk in endpoint */ | 681 | /* we found a bulk in endpoint */ |
683 | dbg("found bulk in on endpoint %d", i); | 682 | dbg("found bulk in on endpoint %d", i); |
684 | bulk_in_endpoint[num_bulk_in] = endpoint; | 683 | bulk_in_endpoint[num_bulk_in] = endpoint; |
685 | ++num_bulk_in; | 684 | ++num_bulk_in; |
686 | } | 685 | } |
687 | 686 | ||
688 | if (((endpoint->bEndpointAddress & 0x80) == 0x00) && | 687 | if (usb_endpoint_is_bulk_out(endpoint)) { |
689 | ((endpoint->bmAttributes & 3) == 0x02)) { | ||
690 | /* we found a bulk out endpoint */ | 688 | /* we found a bulk out endpoint */ |
691 | dbg("found bulk out on endpoint %d", i); | 689 | dbg("found bulk out on endpoint %d", i); |
692 | bulk_out_endpoint[num_bulk_out] = endpoint; | 690 | bulk_out_endpoint[num_bulk_out] = endpoint; |
693 | ++num_bulk_out; | 691 | ++num_bulk_out; |
694 | } | 692 | } |
695 | 693 | ||
696 | if ((endpoint->bEndpointAddress & 0x80) && | 694 | if (usb_endpoint_is_int_in(endpoint)) { |
697 | ((endpoint->bmAttributes & 3) == 0x03)) { | ||
698 | /* we found a interrupt in endpoint */ | 695 | /* we found a interrupt in endpoint */ |
699 | dbg("found interrupt in on endpoint %d", i); | 696 | dbg("found interrupt in on endpoint %d", i); |
700 | interrupt_in_endpoint[num_interrupt_in] = endpoint; | 697 | interrupt_in_endpoint[num_interrupt_in] = endpoint; |
701 | ++num_interrupt_in; | 698 | ++num_interrupt_in; |
702 | } | 699 | } |
703 | 700 | ||
704 | if (((endpoint->bEndpointAddress & 0x80) == 0x00) && | 701 | if (usb_endpoint_is_int_out(endpoint)) { |
705 | ((endpoint->bmAttributes & 3) == 0x03)) { | ||
706 | /* we found an interrupt out endpoint */ | 702 | /* we found an interrupt out endpoint */ |
707 | dbg("found interrupt out on endpoint %d", i); | 703 | dbg("found interrupt out on endpoint %d", i); |
708 | interrupt_out_endpoint[num_interrupt_out] = endpoint; | 704 | interrupt_out_endpoint[num_interrupt_out] = endpoint; |
@@ -716,14 +712,15 @@ int usb_serial_probe(struct usb_interface *interface, | |||
716 | if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && | 712 | if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && |
717 | (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) || | 713 | (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) || |
718 | ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) && | 714 | ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) && |
719 | (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID))) { | 715 | (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) || |
716 | ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) && | ||
717 | (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) { | ||
720 | if (interface != dev->actconfig->interface[0]) { | 718 | if (interface != dev->actconfig->interface[0]) { |
721 | /* check out the endpoints of the other interface*/ | 719 | /* check out the endpoints of the other interface*/ |
722 | iface_desc = dev->actconfig->interface[0]->cur_altsetting; | 720 | iface_desc = dev->actconfig->interface[0]->cur_altsetting; |
723 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 721 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
724 | endpoint = &iface_desc->endpoint[i].desc; | 722 | endpoint = &iface_desc->endpoint[i].desc; |
725 | if ((endpoint->bEndpointAddress & 0x80) && | 723 | if (usb_endpoint_is_int_in(endpoint)) { |
726 | ((endpoint->bmAttributes & 3) == 0x03)) { | ||
727 | /* we found a interrupt in endpoint */ | 724 | /* we found a interrupt in endpoint */ |
728 | dbg("found interrupt in for Prolific device on separate interface"); | 725 | dbg("found interrupt in for Prolific device on separate interface"); |
729 | interrupt_in_endpoint[num_interrupt_in] = endpoint; | 726 | interrupt_in_endpoint[num_interrupt_in] = endpoint; |
@@ -937,7 +934,10 @@ int usb_serial_probe(struct usb_interface *interface, | |||
937 | 934 | ||
938 | snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number); | 935 | snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number); |
939 | dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id); | 936 | dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id); |
940 | device_register (&port->dev); | 937 | retval = device_register(&port->dev); |
938 | if (retval) | ||
939 | dev_err(&port->dev, "Error registering port device, " | ||
940 | "continuing\n"); | ||
941 | } | 941 | } |
942 | 942 | ||
943 | usb_serial_console_init (debug, minor); | 943 | usb_serial_console_init (debug, minor); |
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index be9eec225743..86e48c42d6af 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -135,6 +135,18 @@ config USB_STORAGE_ONETOUCH | |||
135 | this input in any keybinding software. (e.g. gnome's keyboard short- | 135 | this input in any keybinding software. (e.g. gnome's keyboard short- |
136 | cuts) | 136 | cuts) |
137 | 137 | ||
138 | config USB_STORAGE_KARMA | ||
139 | bool "Support for Rio Karma music player" | ||
140 | depends on USB_STORAGE | ||
141 | help | ||
142 | Say Y here to include additional code to support the Rio Karma | ||
143 | USB interface. | ||
144 | |||
145 | This code places the Rio Karma into mass storage mode, enabling | ||
146 | it to be mounted as an ordinary filesystem. Performing an eject | ||
147 | on the resulting scsi device node returns the Karma to normal | ||
148 | operation. | ||
149 | |||
138 | config USB_LIBUSUAL | 150 | config USB_LIBUSUAL |
139 | bool "The shared table of common (or usual) storage devices" | 151 | bool "The shared table of common (or usual) storage devices" |
140 | depends on USB | 152 | depends on USB |
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 8cbba22508a4..023969b4385b 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile | |||
@@ -20,6 +20,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o | |||
20 | usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o | 20 | usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o |
21 | usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o | 21 | usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o |
22 | usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o | 22 | usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o |
23 | usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o | ||
23 | 24 | ||
24 | usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ | 25 | usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ |
25 | initializers.o $(usb-storage-obj-y) | 26 | initializers.o $(usb-storage-obj-y) |
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index ab173b30076e..5b06f9240d05 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c | |||
@@ -45,12 +45,6 @@ | |||
45 | #include "debug.h" | 45 | #include "debug.h" |
46 | #include "transport.h" | 46 | #include "transport.h" |
47 | 47 | ||
48 | #define RIO_MSC 0x08 | ||
49 | #define RIOP_INIT "RIOP\x00\x01\x08" | ||
50 | #define RIOP_INIT_LEN 7 | ||
51 | #define RIO_SEND_LEN 40 | ||
52 | #define RIO_RECV_LEN 0x200 | ||
53 | |||
54 | /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target | 48 | /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target |
55 | * mode */ | 49 | * mode */ |
56 | int usb_stor_euscsi_init(struct us_data *us) | 50 | int usb_stor_euscsi_init(struct us_data *us) |
@@ -97,70 +91,3 @@ int usb_stor_ucr61s2b_init(struct us_data *us) | |||
97 | 91 | ||
98 | return (res ? -1 : 0); | 92 | return (res ? -1 : 0); |
99 | } | 93 | } |
100 | |||
101 | /* Place the Rio Karma into mass storage mode. | ||
102 | * | ||
103 | * The initialization begins by sending 40 bytes starting | ||
104 | * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte | ||
105 | * packet with the high four bits set and everything else null. | ||
106 | * | ||
107 | * Next, we send RIOP\x80\x00\x08\x00. Each time, a 512 byte response | ||
108 | * must be read, but we must loop until byte 5 in the response is 0x08, | ||
109 | * indicating success. */ | ||
110 | int rio_karma_init(struct us_data *us) | ||
111 | { | ||
112 | int result, partial; | ||
113 | char *recv; | ||
114 | unsigned long timeout; | ||
115 | |||
116 | // us->iobuf is big enough to hold cmd but not receive | ||
117 | if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL))) | ||
118 | goto die_nomem; | ||
119 | |||
120 | US_DEBUGP("Initializing Karma...\n"); | ||
121 | |||
122 | memset(us->iobuf, 0, RIO_SEND_LEN); | ||
123 | memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN); | ||
124 | |||
125 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
126 | us->iobuf, RIO_SEND_LEN, &partial); | ||
127 | if (result != USB_STOR_XFER_GOOD) | ||
128 | goto die; | ||
129 | |||
130 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
131 | recv, RIO_RECV_LEN, &partial); | ||
132 | if (result != USB_STOR_XFER_GOOD) | ||
133 | goto die; | ||
134 | |||
135 | us->iobuf[4] = 0x80; | ||
136 | us->iobuf[5] = 0; | ||
137 | timeout = jiffies + msecs_to_jiffies(3000); | ||
138 | for (;;) { | ||
139 | US_DEBUGP("Sending init command\n"); | ||
140 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
141 | us->iobuf, RIO_SEND_LEN, &partial); | ||
142 | if (result != USB_STOR_XFER_GOOD) | ||
143 | goto die; | ||
144 | |||
145 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
146 | recv, RIO_RECV_LEN, &partial); | ||
147 | if (result != USB_STOR_XFER_GOOD) | ||
148 | goto die; | ||
149 | |||
150 | if (recv[5] == RIO_MSC) | ||
151 | break; | ||
152 | if (time_after(jiffies, timeout)) | ||
153 | goto die; | ||
154 | msleep(10); | ||
155 | } | ||
156 | US_DEBUGP("Karma initialized.\n"); | ||
157 | kfree(recv); | ||
158 | return 0; | ||
159 | |||
160 | die: | ||
161 | kfree(recv); | ||
162 | die_nomem: | ||
163 | US_DEBUGP("Could not initialize karma.\n"); | ||
164 | return USB_STOR_TRANSPORT_FAILED; | ||
165 | } | ||
166 | |||
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 927f7781080f..e2967a4d48a2 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h | |||
@@ -47,4 +47,3 @@ int usb_stor_euscsi_init(struct us_data *us); | |||
47 | /* This function is required to activate all four slots on the UCR-61S2B | 47 | /* This function is required to activate all four slots on the UCR-61S2B |
48 | * flash reader */ | 48 | * flash reader */ |
49 | int usb_stor_ucr61s2b_init(struct us_data *us); | 49 | int usb_stor_ucr61s2b_init(struct us_data *us); |
50 | int rio_karma_init(struct us_data *us); | ||
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c new file mode 100644 index 000000000000..0d79ae5683f7 --- /dev/null +++ b/drivers/usb/storage/karma.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* Driver for Rio Karma | ||
2 | * | ||
3 | * (c) 2006 Bob Copeland <me@bobcopeland.com> | ||
4 | * (c) 2006 Keith Bennett <keith@mcs.st-and.ac.uk> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2, or (at your option) any | ||
9 | * later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <scsi/scsi.h> | ||
22 | #include <scsi/scsi_cmnd.h> | ||
23 | #include <scsi/scsi_device.h> | ||
24 | |||
25 | #include "usb.h" | ||
26 | #include "transport.h" | ||
27 | #include "debug.h" | ||
28 | #include "karma.h" | ||
29 | |||
30 | #define RIO_PREFIX "RIOP\x00" | ||
31 | #define RIO_PREFIX_LEN 5 | ||
32 | #define RIO_SEND_LEN 40 | ||
33 | #define RIO_RECV_LEN 0x200 | ||
34 | |||
35 | #define RIO_ENTER_STORAGE 0x1 | ||
36 | #define RIO_LEAVE_STORAGE 0x2 | ||
37 | #define RIO_RESET 0xC | ||
38 | |||
39 | extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *); | ||
40 | |||
41 | struct karma_data { | ||
42 | int in_storage; | ||
43 | char *recv; | ||
44 | }; | ||
45 | |||
46 | /* | ||
47 | * Send commands to Rio Karma. | ||
48 | * | ||
49 | * For each command we send 40 bytes starting 'RIOP\0' followed by | ||
50 | * the command number and a sequence number, which the device will ack | ||
51 | * with a 512-byte packet with the high four bits set and everything | ||
52 | * else null. Then we send 'RIOP\x80' followed by a zero and the | ||
53 | * sequence number, until byte 5 in the response repeats the sequence | ||
54 | * number. | ||
55 | */ | ||
56 | static int rio_karma_send_command(char cmd, struct us_data *us) | ||
57 | { | ||
58 | int result, partial; | ||
59 | unsigned long timeout; | ||
60 | static unsigned char seq = 1; | ||
61 | struct karma_data *data = (struct karma_data *) us->extra; | ||
62 | |||
63 | US_DEBUGP("karma: sending command %04x\n", cmd); | ||
64 | memset(us->iobuf, 0, RIO_SEND_LEN); | ||
65 | memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN); | ||
66 | us->iobuf[5] = cmd; | ||
67 | us->iobuf[6] = seq; | ||
68 | |||
69 | timeout = jiffies + msecs_to_jiffies(6000); | ||
70 | for (;;) { | ||
71 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | ||
72 | us->iobuf, RIO_SEND_LEN, &partial); | ||
73 | if (result != USB_STOR_XFER_GOOD) | ||
74 | goto err; | ||
75 | |||
76 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | ||
77 | data->recv, RIO_RECV_LEN, &partial); | ||
78 | if (result != USB_STOR_XFER_GOOD) | ||
79 | goto err; | ||
80 | |||
81 | if (data->recv[5] == seq) | ||
82 | break; | ||
83 | |||
84 | if (time_after(jiffies, timeout)) | ||
85 | goto err; | ||
86 | |||
87 | us->iobuf[4] = 0x80; | ||
88 | us->iobuf[5] = 0; | ||
89 | msleep(50); | ||
90 | } | ||
91 | |||
92 | seq++; | ||
93 | if (seq == 0) | ||
94 | seq = 1; | ||
95 | |||
96 | US_DEBUGP("karma: sent command %04x\n", cmd); | ||
97 | return 0; | ||
98 | err: | ||
99 | US_DEBUGP("karma: command %04x failed\n", cmd); | ||
100 | return USB_STOR_TRANSPORT_FAILED; | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Trap START_STOP and READ_10 to leave/re-enter storage mode. | ||
105 | * Everything else is propagated to the normal bulk layer. | ||
106 | */ | ||
107 | int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
108 | { | ||
109 | int ret; | ||
110 | struct karma_data *data = (struct karma_data *) us->extra; | ||
111 | |||
112 | if (srb->cmnd[0] == READ_10 && !data->in_storage) { | ||
113 | ret = rio_karma_send_command(RIO_ENTER_STORAGE, us); | ||
114 | if (ret) | ||
115 | return ret; | ||
116 | |||
117 | data->in_storage = 1; | ||
118 | return usb_stor_Bulk_transport(srb, us); | ||
119 | } else if (srb->cmnd[0] == START_STOP) { | ||
120 | ret = rio_karma_send_command(RIO_LEAVE_STORAGE, us); | ||
121 | if (ret) | ||
122 | return ret; | ||
123 | |||
124 | data->in_storage = 0; | ||
125 | return rio_karma_send_command(RIO_RESET, us); | ||
126 | } | ||
127 | return usb_stor_Bulk_transport(srb, us); | ||
128 | } | ||
129 | |||
130 | static void rio_karma_destructor(void *extra) | ||
131 | { | ||
132 | struct karma_data *data = (struct karma_data *) extra; | ||
133 | kfree(data->recv); | ||
134 | } | ||
135 | |||
136 | int rio_karma_init(struct us_data *us) | ||
137 | { | ||
138 | int ret = 0; | ||
139 | struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO); | ||
140 | if (!data) | ||
141 | goto out; | ||
142 | |||
143 | data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO); | ||
144 | if (!data->recv) { | ||
145 | kfree(data); | ||
146 | goto out; | ||
147 | } | ||
148 | |||
149 | us->extra = data; | ||
150 | us->extra_destructor = rio_karma_destructor; | ||
151 | ret = rio_karma_send_command(RIO_ENTER_STORAGE, us); | ||
152 | data->in_storage = (ret == 0); | ||
153 | out: | ||
154 | return ret; | ||
155 | } | ||
diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h new file mode 100644 index 000000000000..8a60972af8c5 --- /dev/null +++ b/drivers/usb/storage/karma.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _KARMA_USB_H | ||
2 | #define _KARMA_USB_H | ||
3 | |||
4 | extern int rio_karma_init(struct us_data *us); | ||
5 | extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us); | ||
6 | |||
7 | #endif | ||
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c index b1ec4a718547..599ad10a761b 100644 --- a/drivers/usb/storage/libusual.c +++ b/drivers/usb/storage/libusual.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/usb.h> | 8 | #include <linux/usb.h> |
9 | #include <linux/usb_usual.h> | 9 | #include <linux/usb_usual.h> |
10 | #include <linux/vmalloc.h> | 10 | #include <linux/vmalloc.h> |
11 | #include <linux/kthread.h> | ||
11 | 12 | ||
12 | /* | 13 | /* |
13 | */ | 14 | */ |
@@ -117,7 +118,7 @@ static int usu_probe(struct usb_interface *intf, | |||
117 | const struct usb_device_id *id) | 118 | const struct usb_device_id *id) |
118 | { | 119 | { |
119 | unsigned long type; | 120 | unsigned long type; |
120 | int rc; | 121 | struct task_struct* task; |
121 | unsigned long flags; | 122 | unsigned long flags; |
122 | 123 | ||
123 | type = USB_US_TYPE(id->driver_info); | 124 | type = USB_US_TYPE(id->driver_info); |
@@ -132,8 +133,9 @@ static int usu_probe(struct usb_interface *intf, | |||
132 | stat[type].fls |= USU_MOD_FL_THREAD; | 133 | stat[type].fls |= USU_MOD_FL_THREAD; |
133 | spin_unlock_irqrestore(&usu_lock, flags); | 134 | spin_unlock_irqrestore(&usu_lock, flags); |
134 | 135 | ||
135 | rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM); | 136 | task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type); |
136 | if (rc < 0) { | 137 | if (IS_ERR(task)) { |
138 | int rc = PTR_ERR(task); | ||
137 | printk(KERN_WARNING "libusual: " | 139 | printk(KERN_WARNING "libusual: " |
138 | "Unable to start the thread for %s: %d\n", | 140 | "Unable to start the thread for %s: %d\n", |
139 | bias_names[type], rc); | 141 | bias_names[type], rc); |
@@ -175,8 +177,6 @@ static int usu_probe_thread(void *arg) | |||
175 | int rc; | 177 | int rc; |
176 | unsigned long flags; | 178 | unsigned long flags; |
177 | 179 | ||
178 | daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */ | ||
179 | |||
180 | /* A completion does not work here because it's counted. */ | 180 | /* A completion does not work here because it's counted. */ |
181 | down(&usu_init_notify); | 181 | down(&usu_init_notify); |
182 | up(&usu_init_notify); | 182 | up(&usu_init_notify); |
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 313920d980c9..f843a0bcf107 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c | |||
@@ -135,6 +135,7 @@ int onetouch_connect_input(struct us_data *ss) | |||
135 | struct usb_onetouch *onetouch; | 135 | struct usb_onetouch *onetouch; |
136 | struct input_dev *input_dev; | 136 | struct input_dev *input_dev; |
137 | int pipe, maxp; | 137 | int pipe, maxp; |
138 | int error = -ENOMEM; | ||
138 | 139 | ||
139 | interface = ss->pusb_intf->cur_altsetting; | 140 | interface = ss->pusb_intf->cur_altsetting; |
140 | 141 | ||
@@ -211,15 +212,18 @@ int onetouch_connect_input(struct us_data *ss) | |||
211 | ss->suspend_resume_hook = usb_onetouch_pm_hook; | 212 | ss->suspend_resume_hook = usb_onetouch_pm_hook; |
212 | #endif | 213 | #endif |
213 | 214 | ||
214 | input_register_device(onetouch->dev); | 215 | error = input_register_device(onetouch->dev); |
216 | if (error) | ||
217 | goto fail3; | ||
215 | 218 | ||
216 | return 0; | 219 | return 0; |
217 | 220 | ||
221 | fail3: usb_free_urb(onetouch->irq); | ||
218 | fail2: usb_buffer_free(udev, ONETOUCH_PKT_LEN, | 222 | fail2: usb_buffer_free(udev, ONETOUCH_PKT_LEN, |
219 | onetouch->data, onetouch->data_dma); | 223 | onetouch->data, onetouch->data_dma); |
220 | fail1: kfree(onetouch); | 224 | fail1: kfree(onetouch); |
221 | input_free_device(input_dev); | 225 | input_free_device(input_dev); |
222 | return -ENOMEM; | 226 | return error; |
223 | } | 227 | } |
224 | 228 | ||
225 | void onetouch_release_input(void *onetouch_) | 229 | void onetouch_release_input(void *onetouch_) |
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index a4b7df9ff8c1..e1072d52d641 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c | |||
@@ -72,12 +72,27 @@ static const char* host_info(struct Scsi_Host *host) | |||
72 | 72 | ||
73 | static int slave_alloc (struct scsi_device *sdev) | 73 | static int slave_alloc (struct scsi_device *sdev) |
74 | { | 74 | { |
75 | struct us_data *us = host_to_us(sdev->host); | ||
76 | |||
75 | /* | 77 | /* |
76 | * Set the INQUIRY transfer length to 36. We don't use any of | 78 | * Set the INQUIRY transfer length to 36. We don't use any of |
77 | * the extra data and many devices choke if asked for more or | 79 | * the extra data and many devices choke if asked for more or |
78 | * less than 36 bytes. | 80 | * less than 36 bytes. |
79 | */ | 81 | */ |
80 | sdev->inquiry_len = 36; | 82 | sdev->inquiry_len = 36; |
83 | |||
84 | /* | ||
85 | * The UFI spec treates the Peripheral Qualifier bits in an | ||
86 | * INQUIRY result as reserved and requires devices to set them | ||
87 | * to 0. However the SCSI spec requires these bits to be set | ||
88 | * to 3 to indicate when a LUN is not present. | ||
89 | * | ||
90 | * Let the scanning code know if this target merely sets | ||
91 | * Peripheral Device Type to 0x1f to indicate no LUN. | ||
92 | */ | ||
93 | if (us->subclass == US_SC_UFI) | ||
94 | sdev->sdev_target->pdt_1f_for_no_lun = 1; | ||
95 | |||
81 | return 0; | 96 | return 0; |
82 | } | 97 | } |
83 | 98 | ||
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index d6acc92a4ae3..f23514c4e649 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -294,11 +294,6 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe, | |||
294 | return USB_STOR_XFER_ERROR; | 294 | return USB_STOR_XFER_ERROR; |
295 | return USB_STOR_XFER_STALLED; | 295 | return USB_STOR_XFER_STALLED; |
296 | 296 | ||
297 | /* timeout or excessively long NAK */ | ||
298 | case -ETIMEDOUT: | ||
299 | US_DEBUGP("-- timeout or NAK\n"); | ||
300 | return USB_STOR_XFER_ERROR; | ||
301 | |||
302 | /* babble - the device tried to send more than we wanted to read */ | 297 | /* babble - the device tried to send more than we wanted to read */ |
303 | case -EOVERFLOW: | 298 | case -EOVERFLOW: |
304 | US_DEBUGP("-- babble\n"); | 299 | US_DEBUGP("-- babble\n"); |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index b130e170b4a8..40bf159f7d54 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -218,10 +218,12 @@ UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, | |||
218 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 218 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
219 | US_FL_NOT_LOCKABLE ), | 219 | US_FL_NOT_LOCKABLE ), |
220 | 220 | ||
221 | #ifdef CONFIG_USB_STORAGE_KARMA | ||
221 | UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, | 222 | UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, |
222 | "Rio", | 223 | "Rio", |
223 | "Rio Karma", | 224 | "Rio Karma", |
224 | US_SC_SCSI, US_PR_BULK, rio_karma_init, 0), | 225 | US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), |
226 | #endif | ||
225 | 227 | ||
226 | /* Patch submitted by Philipp Friedrich <philipp@void.at> */ | 228 | /* Patch submitted by Philipp Friedrich <philipp@void.at> */ |
227 | UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, | 229 | UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, |
@@ -631,6 +633,13 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, | |||
631 | "Digital Camera EX-20 DSC", | 633 | "Digital Camera EX-20 DSC", |
632 | US_SC_8070, US_PR_DEVICE, NULL, 0 ), | 634 | US_SC_8070, US_PR_DEVICE, NULL, 0 ), |
633 | 635 | ||
636 | /* Reported by <Hendryk.Pfeiffer@gmx.de> */ | ||
637 | UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, | ||
638 | "LaCie", | ||
639 | "DVD+-RW", | ||
640 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
641 | US_FL_GO_SLOW ), | ||
642 | |||
634 | /* Submitted by Joel Bourquard <numlock@freesurf.ch> | 643 | /* Submitted by Joel Bourquard <numlock@freesurf.ch> |
635 | * Some versions of this device need the SubClass and Protocol overrides | 644 | * Some versions of this device need the SubClass and Protocol overrides |
636 | * while others don't. | 645 | * while others don't. |
@@ -1254,6 +1263,13 @@ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, | |||
1254 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1263 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1255 | US_FL_NO_WP_DETECT ), | 1264 | US_FL_NO_WP_DETECT ), |
1256 | 1265 | ||
1266 | /* Reported by Jan Mate <mate@fiit.stuba.sk> */ | ||
1267 | UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, | ||
1268 | "Sony Ericsson", | ||
1269 | "P990i", | ||
1270 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1271 | US_FL_FIX_CAPACITY ), | ||
1272 | |||
1257 | /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */ | 1273 | /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */ |
1258 | UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, | 1274 | UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, |
1259 | "Sony Ericsson", | 1275 | "Sony Ericsson", |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 8d7bdcb5924d..b8d6031b0975 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -98,6 +98,9 @@ | |||
98 | #ifdef CONFIG_USB_STORAGE_ALAUDA | 98 | #ifdef CONFIG_USB_STORAGE_ALAUDA |
99 | #include "alauda.h" | 99 | #include "alauda.h" |
100 | #endif | 100 | #endif |
101 | #ifdef CONFIG_USB_STORAGE_KARMA | ||
102 | #include "karma.h" | ||
103 | #endif | ||
101 | 104 | ||
102 | /* Some informational data */ | 105 | /* Some informational data */ |
103 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); | 106 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); |
@@ -646,6 +649,14 @@ static int get_transport(struct us_data *us) | |||
646 | break; | 649 | break; |
647 | #endif | 650 | #endif |
648 | 651 | ||
652 | #ifdef CONFIG_USB_STORAGE_KARMA | ||
653 | case US_PR_KARMA: | ||
654 | us->transport_name = "Rio Karma/Bulk"; | ||
655 | us->transport = rio_karma_transport; | ||
656 | us->transport_reset = usb_stor_Bulk_reset; | ||
657 | break; | ||
658 | #endif | ||
659 | |||
649 | default: | 660 | default: |
650 | return -EIO; | 661 | return -EIO; |
651 | } | 662 | } |
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index b362039792b3..1b51d3187a95 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * USB Skeleton driver - 2.0 | 2 | * USB Skeleton driver - 2.2 |
3 | * | 3 | * |
4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) |
5 | * | 5 | * |
@@ -7,9 +7,8 @@ | |||
7 | * modify it under the terms of the GNU General Public License as | 7 | * modify it under the terms of the GNU General Public License as |
8 | * published by the Free Software Foundation, version 2. | 8 | * published by the Free Software Foundation, version 2. |
9 | * | 9 | * |
10 | * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c | 10 | * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c |
11 | * but has been rewritten to be easy to read and use, as no locks are now | 11 | * but has been rewritten to be easier to read and use. |
12 | * needed anymore. | ||
13 | * | 12 | * |
14 | */ | 13 | */ |
15 | 14 | ||
@@ -21,6 +20,7 @@ | |||
21 | #include <linux/kref.h> | 20 | #include <linux/kref.h> |
22 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
23 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
23 | #include <linux/mutex.h> | ||
24 | 24 | ||
25 | 25 | ||
26 | /* Define these values to match your devices */ | 26 | /* Define these values to match your devices */ |
@@ -32,38 +32,39 @@ static struct usb_device_id skel_table [] = { | |||
32 | { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, | 32 | { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, |
33 | { } /* Terminating entry */ | 33 | { } /* Terminating entry */ |
34 | }; | 34 | }; |
35 | MODULE_DEVICE_TABLE (usb, skel_table); | 35 | MODULE_DEVICE_TABLE(usb, skel_table); |
36 | 36 | ||
37 | 37 | ||
38 | /* Get a minor range for your devices from the usb maintainer */ | 38 | /* Get a minor range for your devices from the usb maintainer */ |
39 | #define USB_SKEL_MINOR_BASE 192 | 39 | #define USB_SKEL_MINOR_BASE 192 |
40 | 40 | ||
41 | /* our private defines. if this grows any larger, use your own .h file */ | 41 | /* our private defines. if this grows any larger, use your own .h file */ |
42 | #define MAX_TRANSFER ( PAGE_SIZE - 512 ) | 42 | #define MAX_TRANSFER (PAGE_SIZE - 512) |
43 | #define WRITES_IN_FLIGHT 8 | 43 | #define WRITES_IN_FLIGHT 8 |
44 | 44 | ||
45 | /* Structure to hold all of our device specific stuff */ | 45 | /* Structure to hold all of our device specific stuff */ |
46 | struct usb_skel { | 46 | struct usb_skel { |
47 | struct usb_device * udev; /* the usb device for this device */ | 47 | struct usb_device *dev; /* the usb device for this device */ |
48 | struct usb_interface * interface; /* the interface for this device */ | 48 | struct usb_interface *interface; /* the interface for this device */ |
49 | struct semaphore limit_sem; /* limiting the number of writes in progress */ | 49 | struct semaphore limit_sem; /* limiting the number of writes in progress */ |
50 | unsigned char * bulk_in_buffer; /* the buffer to receive data */ | 50 | unsigned char *bulk_in_buffer; /* the buffer to receive data */ |
51 | size_t bulk_in_size; /* the size of the receive buffer */ | 51 | size_t bulk_in_size; /* the size of the receive buffer */ |
52 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ | 52 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ |
53 | __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ | 53 | __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ |
54 | struct kref kref; | 54 | struct kref kref; |
55 | struct mutex io_mutex; /* synchronize I/O with disconnect */ | ||
55 | }; | 56 | }; |
56 | #define to_skel_dev(d) container_of(d, struct usb_skel, kref) | 57 | #define to_skel_dev(d) container_of(d, struct usb_skel, kref) |
57 | 58 | ||
58 | static struct usb_driver skel_driver; | 59 | static struct usb_driver skel_driver; |
59 | 60 | ||
60 | static void skel_delete(struct kref *kref) | 61 | static void skel_delete(struct kref *kref) |
61 | { | 62 | { |
62 | struct usb_skel *dev = to_skel_dev(kref); | 63 | struct usb_skel *dev = to_skel_dev(kref); |
63 | 64 | ||
64 | usb_put_dev(dev->udev); | 65 | usb_put_dev(dev->udev); |
65 | kfree (dev->bulk_in_buffer); | 66 | kfree(dev->bulk_in_buffer); |
66 | kfree (dev); | 67 | kfree(dev); |
67 | } | 68 | } |
68 | 69 | ||
69 | static int skel_open(struct inode *inode, struct file *file) | 70 | static int skel_open(struct inode *inode, struct file *file) |
@@ -89,6 +90,11 @@ static int skel_open(struct inode *inode, struct file *file) | |||
89 | goto exit; | 90 | goto exit; |
90 | } | 91 | } |
91 | 92 | ||
93 | /* prevent the device from being autosuspended */ | ||
94 | retval = usb_autopm_get_interface(interface); | ||
95 | if (retval) | ||
96 | goto exit; | ||
97 | |||
92 | /* increment our usage count for the device */ | 98 | /* increment our usage count for the device */ |
93 | kref_get(&dev->kref); | 99 | kref_get(&dev->kref); |
94 | 100 | ||
@@ -107,6 +113,12 @@ static int skel_release(struct inode *inode, struct file *file) | |||
107 | if (dev == NULL) | 113 | if (dev == NULL) |
108 | return -ENODEV; | 114 | return -ENODEV; |
109 | 115 | ||
116 | /* allow the device to be autosuspended */ | ||
117 | mutex_lock(&dev->io_mutex); | ||
118 | if (dev->interface) | ||
119 | usb_autopm_put_interface(dev->interface); | ||
120 | mutex_unlock(&dev->io_mutex); | ||
121 | |||
110 | /* decrement the count on our device */ | 122 | /* decrement the count on our device */ |
111 | kref_put(&dev->kref, skel_delete); | 123 | kref_put(&dev->kref, skel_delete); |
112 | return 0; | 124 | return 0; |
@@ -115,11 +127,17 @@ static int skel_release(struct inode *inode, struct file *file) | |||
115 | static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos) | 127 | static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos) |
116 | { | 128 | { |
117 | struct usb_skel *dev; | 129 | struct usb_skel *dev; |
118 | int retval = 0; | 130 | int retval; |
119 | int bytes_read; | 131 | int bytes_read; |
120 | 132 | ||
121 | dev = (struct usb_skel *)file->private_data; | 133 | dev = (struct usb_skel *)file->private_data; |
122 | 134 | ||
135 | mutex_lock(&dev->io_mutex); | ||
136 | if (!dev->interface) { /* disconnect() was called */ | ||
137 | retval = -ENODEV; | ||
138 | goto exit; | ||
139 | } | ||
140 | |||
123 | /* do a blocking bulk read to get data from the device */ | 141 | /* do a blocking bulk read to get data from the device */ |
124 | retval = usb_bulk_msg(dev->udev, | 142 | retval = usb_bulk_msg(dev->udev, |
125 | usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), | 143 | usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), |
@@ -135,6 +153,8 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t * | |||
135 | retval = bytes_read; | 153 | retval = bytes_read; |
136 | } | 154 | } |
137 | 155 | ||
156 | exit: | ||
157 | mutex_unlock(&dev->io_mutex); | ||
138 | return retval; | 158 | return retval; |
139 | } | 159 | } |
140 | 160 | ||
@@ -145,16 +165,16 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
145 | dev = (struct usb_skel *)urb->context; | 165 | dev = (struct usb_skel *)urb->context; |
146 | 166 | ||
147 | /* sync/async unlink faults aren't errors */ | 167 | /* sync/async unlink faults aren't errors */ |
148 | if (urb->status && | 168 | if (urb->status && |
149 | !(urb->status == -ENOENT || | 169 | !(urb->status == -ENOENT || |
150 | urb->status == -ECONNRESET || | 170 | urb->status == -ECONNRESET || |
151 | urb->status == -ESHUTDOWN)) { | 171 | urb->status == -ESHUTDOWN)) { |
152 | dbg("%s - nonzero write bulk status received: %d", | 172 | err("%s - nonzero write bulk status received: %d", |
153 | __FUNCTION__, urb->status); | 173 | __FUNCTION__, urb->status); |
154 | } | 174 | } |
155 | 175 | ||
156 | /* free up our allocated buffer */ | 176 | /* free up our allocated buffer */ |
157 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | 177 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, |
158 | urb->transfer_buffer, urb->transfer_dma); | 178 | urb->transfer_buffer, urb->transfer_dma); |
159 | up(&dev->limit_sem); | 179 | up(&dev->limit_sem); |
160 | } | 180 | } |
@@ -179,6 +199,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou | |||
179 | goto exit; | 199 | goto exit; |
180 | } | 200 | } |
181 | 201 | ||
202 | mutex_lock(&dev->io_mutex); | ||
203 | if (!dev->interface) { /* disconnect() was called */ | ||
204 | retval = -ENODEV; | ||
205 | goto error; | ||
206 | } | ||
207 | |||
182 | /* create a urb, and a buffer for it, and copy the data to the urb */ | 208 | /* create a urb, and a buffer for it, and copy the data to the urb */ |
183 | urb = usb_alloc_urb(0, GFP_KERNEL); | 209 | urb = usb_alloc_urb(0, GFP_KERNEL); |
184 | if (!urb) { | 210 | if (!urb) { |
@@ -213,17 +239,22 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou | |||
213 | /* release our reference to this urb, the USB core will eventually free it entirely */ | 239 | /* release our reference to this urb, the USB core will eventually free it entirely */ |
214 | usb_free_urb(urb); | 240 | usb_free_urb(urb); |
215 | 241 | ||
216 | exit: | 242 | mutex_unlock(&dev->io_mutex); |
217 | return writesize; | 243 | return writesize; |
218 | 244 | ||
219 | error: | 245 | error: |
220 | usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); | 246 | if (urb) { |
221 | usb_free_urb(urb); | 247 | usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); |
248 | usb_free_urb(urb); | ||
249 | } | ||
250 | mutex_unlock(&dev->io_mutex); | ||
222 | up(&dev->limit_sem); | 251 | up(&dev->limit_sem); |
252 | |||
253 | exit: | ||
223 | return retval; | 254 | return retval; |
224 | } | 255 | } |
225 | 256 | ||
226 | static struct file_operations skel_fops = { | 257 | static const struct file_operations skel_fops = { |
227 | .owner = THIS_MODULE, | 258 | .owner = THIS_MODULE, |
228 | .read = skel_read, | 259 | .read = skel_read, |
229 | .write = skel_write, | 260 | .write = skel_write, |
@@ -231,7 +262,7 @@ static struct file_operations skel_fops = { | |||
231 | .release = skel_release, | 262 | .release = skel_release, |
232 | }; | 263 | }; |
233 | 264 | ||
234 | /* | 265 | /* |
235 | * usb class driver info in order to get a minor number from the usb core, | 266 | * usb class driver info in order to get a minor number from the usb core, |
236 | * and to have the device registered with the driver core | 267 | * and to have the device registered with the driver core |
237 | */ | 268 | */ |
@@ -243,7 +274,7 @@ static struct usb_class_driver skel_class = { | |||
243 | 274 | ||
244 | static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id) | 275 | static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id) |
245 | { | 276 | { |
246 | struct usb_skel *dev = NULL; | 277 | struct usb_skel *dev; |
247 | struct usb_host_interface *iface_desc; | 278 | struct usb_host_interface *iface_desc; |
248 | struct usb_endpoint_descriptor *endpoint; | 279 | struct usb_endpoint_descriptor *endpoint; |
249 | size_t buffer_size; | 280 | size_t buffer_size; |
@@ -252,12 +283,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i | |||
252 | 283 | ||
253 | /* allocate memory for our device state and initialize it */ | 284 | /* allocate memory for our device state and initialize it */ |
254 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 285 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
255 | if (dev == NULL) { | 286 | if (!dev) { |
256 | err("Out of memory"); | 287 | err("Out of memory"); |
257 | goto error; | 288 | goto error; |
258 | } | 289 | } |
259 | kref_init(&dev->kref); | 290 | kref_init(&dev->kref); |
260 | sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); | 291 | sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); |
292 | mutex_init(&dev->io_mutex); | ||
261 | 293 | ||
262 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 294 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
263 | dev->interface = interface; | 295 | dev->interface = interface; |
@@ -269,10 +301,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i | |||
269 | endpoint = &iface_desc->endpoint[i].desc; | 301 | endpoint = &iface_desc->endpoint[i].desc; |
270 | 302 | ||
271 | if (!dev->bulk_in_endpointAddr && | 303 | if (!dev->bulk_in_endpointAddr && |
272 | ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 304 | usb_endpoint_is_bulk_in(endpoint)) { |
273 | == USB_DIR_IN) && | ||
274 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
275 | == USB_ENDPOINT_XFER_BULK)) { | ||
276 | /* we found a bulk in endpoint */ | 305 | /* we found a bulk in endpoint */ |
277 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 306 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
278 | dev->bulk_in_size = buffer_size; | 307 | dev->bulk_in_size = buffer_size; |
@@ -285,10 +314,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i | |||
285 | } | 314 | } |
286 | 315 | ||
287 | if (!dev->bulk_out_endpointAddr && | 316 | if (!dev->bulk_out_endpointAddr && |
288 | ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 317 | usb_endpoint_is_bulk_out(endpoint)) { |
289 | == USB_DIR_OUT) && | ||
290 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
291 | == USB_ENDPOINT_XFER_BULK)) { | ||
292 | /* we found a bulk out endpoint */ | 318 | /* we found a bulk out endpoint */ |
293 | dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; | 319 | dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; |
294 | } | 320 | } |
@@ -334,6 +360,11 @@ static void skel_disconnect(struct usb_interface *interface) | |||
334 | /* give back our minor */ | 360 | /* give back our minor */ |
335 | usb_deregister_dev(interface, &skel_class); | 361 | usb_deregister_dev(interface, &skel_class); |
336 | 362 | ||
363 | /* prevent more I/O from starting */ | ||
364 | mutex_lock(&dev->io_mutex); | ||
365 | dev->interface = NULL; | ||
366 | mutex_unlock(&dev->io_mutex); | ||
367 | |||
337 | unlock_kernel(); | 368 | unlock_kernel(); |
338 | 369 | ||
339 | /* decrement our usage count */ | 370 | /* decrement our usage count */ |
@@ -367,7 +398,7 @@ static void __exit usb_skel_exit(void) | |||
367 | usb_deregister(&skel_driver); | 398 | usb_deregister(&skel_driver); |
368 | } | 399 | } |
369 | 400 | ||
370 | module_init (usb_skel_init); | 401 | module_init(usb_skel_init); |
371 | module_exit (usb_skel_exit); | 402 | module_exit(usb_skel_exit); |
372 | 403 | ||
373 | MODULE_LICENSE("GPL"); | 404 | MODULE_LICENSE("GPL"); |