You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
This commit is contained in:
@@ -291,7 +291,7 @@
|
||||
|
||||
!Edrivers/usb/core/hcd.c
|
||||
!Edrivers/usb/core/hcd-pci.c
|
||||
!Edrivers/usb/core/buffer.c
|
||||
!Idrivers/usb/core/buffer.c
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
|
||||
@@ -2,7 +2,6 @@ Driver documentation for yealink usb-p1k phones
|
||||
|
||||
0. Status
|
||||
~~~~~~~~~
|
||||
|
||||
The p1k is a relatively cheap usb 1.1 phone with:
|
||||
- keyboard full support, yealink.ko / input event API
|
||||
- LCD full support, yealink.ko / sysfs API
|
||||
@@ -17,9 +16,8 @@ For vendor documentation see http://www.yealink.com
|
||||
|
||||
1. Compilation (stand alone version)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Currently only kernel 2.6.x.y versions are supported.
|
||||
In order to build the yealink.ko module do:
|
||||
In order to build the yealink.ko module do
|
||||
|
||||
make
|
||||
|
||||
@@ -28,6 +26,21 @@ the Makefile is pointing to the location where your kernel sources
|
||||
are located, default /usr/src/linux.
|
||||
|
||||
|
||||
1.1 Troubleshooting
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
Q: Module yealink compiled and installed without any problem but phone
|
||||
is not initialized and does not react to any actions.
|
||||
A: If you see something like:
|
||||
hiddev0: USB HID v1.00 Device [Yealink Network Technology Ltd. VOIP USB Phone
|
||||
in dmesg, it means that the hid driver has grabbed the device first. Try to
|
||||
load module yealink before any other usb hid driver. Please see the
|
||||
instructions provided by your distribution on module configuration.
|
||||
|
||||
Q: Phone is working now (displays version and accepts keypad input) but I can't
|
||||
find the sysfs files.
|
||||
A: The sysfs files are located on the particular usb endpoint. On most
|
||||
distributions you can do: "find /sys/ -name get_icons" for a hint.
|
||||
|
||||
|
||||
2. keyboard features
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -1517,8 +1517,6 @@ running once the system is up.
|
||||
uart6850= [HW,OSS]
|
||||
Format: <io>,<irq>
|
||||
|
||||
usb-handoff [HW] Enable early USB BIOS -> OS handoff
|
||||
|
||||
usbhid.mousepoll=
|
||||
[USBHID] The interval which mice are to be polled at.
|
||||
|
||||
|
||||
+6
-14
@@ -116,12 +116,6 @@ M: ajk@iehk.rwth-aachen.de
|
||||
L: linux-hams@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
YEALINK PHONE DRIVER
|
||||
P: Henk Vergonet
|
||||
M: Henk.Vergonet@gmail.com
|
||||
L: usbb2k-api-dev@nongnu.org
|
||||
S: Maintained
|
||||
|
||||
8139CP 10/100 FAST ETHERNET DRIVER
|
||||
P: Jeff Garzik
|
||||
M: jgarzik@pobox.com
|
||||
@@ -2495,14 +2489,6 @@ L: linux-kernel@vger.kernel.org
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Supported
|
||||
|
||||
USB BLUETOOTH TTY CONVERTER DRIVER
|
||||
P: Greg Kroah-Hartman
|
||||
M: greg@kroah.com
|
||||
L: linux-usb-users@lists.sourceforge.net
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
W: http://www.kroah.com/linux-usb/
|
||||
|
||||
USB CDC ETHERNET DRIVER
|
||||
P: Greg Kroah-Hartman
|
||||
M: greg@kroah.com
|
||||
@@ -2863,6 +2849,12 @@ M: jpr@f6fbb.org
|
||||
L: linux-hams@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
YEALINK PHONE DRIVER
|
||||
P: Henk Vergonet
|
||||
M: Henk.Vergonet@gmail.com
|
||||
L: usbb2k-api-dev@nongnu.org
|
||||
S: Maintained
|
||||
|
||||
YMFPCI YAMAHA PCI SOUND (Use ALSA instead)
|
||||
P: Pete Zaitcev
|
||||
M: zaitcev@yahoo.com
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
# Rewritten to use lists instead of if-statements.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_PCI) += pci/
|
||||
obj-$(CONFIG_PCI) += pci/ usb/
|
||||
obj-$(CONFIG_PARISC) += parisc/
|
||||
obj-y += video/
|
||||
obj-$(CONFIG_ACPI) += acpi/
|
||||
|
||||
@@ -30,23 +30,6 @@ LIST_HEAD(dpm_off_irq);
|
||||
DECLARE_MUTEX(dpm_sem);
|
||||
DECLARE_MUTEX(dpm_list_sem);
|
||||
|
||||
/*
|
||||
* PM Reference Counting.
|
||||
*/
|
||||
|
||||
static inline void device_pm_hold(struct device * dev)
|
||||
{
|
||||
if (dev)
|
||||
atomic_inc(&dev->power.pm_users);
|
||||
}
|
||||
|
||||
static inline void device_pm_release(struct device * dev)
|
||||
{
|
||||
if (dev)
|
||||
atomic_dec(&dev->power.pm_users);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* device_pm_set_parent - Specify power dependency.
|
||||
* @dev: Device who needs power.
|
||||
@@ -62,10 +45,8 @@ static inline void device_pm_release(struct device * dev)
|
||||
|
||||
void device_pm_set_parent(struct device * dev, struct device * parent)
|
||||
{
|
||||
struct device * old_parent = dev->power.pm_parent;
|
||||
device_pm_release(old_parent);
|
||||
dev->power.pm_parent = parent;
|
||||
device_pm_hold(parent);
|
||||
put_device(dev->power.pm_parent);
|
||||
dev->power.pm_parent = get_device(parent);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_pm_set_parent);
|
||||
|
||||
@@ -75,7 +56,6 @@ int device_pm_add(struct device * dev)
|
||||
|
||||
pr_debug("PM: Adding info for %s:%s\n",
|
||||
dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
|
||||
atomic_set(&dev->power.pm_users, 0);
|
||||
down(&dpm_list_sem);
|
||||
list_add_tail(&dev->power.entry, &dpm_active);
|
||||
device_pm_set_parent(dev, dev->parent);
|
||||
@@ -91,7 +71,7 @@ void device_pm_remove(struct device * dev)
|
||||
dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
|
||||
down(&dpm_list_sem);
|
||||
dpm_sysfs_remove(dev);
|
||||
device_pm_release(dev->power.pm_parent);
|
||||
put_device(dev->power.pm_parent);
|
||||
list_del_init(&dev->power.entry);
|
||||
up(&dpm_list_sem);
|
||||
}
|
||||
|
||||
@@ -67,9 +67,6 @@ extern int suspend_device(struct device *, pm_message_t);
|
||||
* runtime.c
|
||||
*/
|
||||
|
||||
extern int dpm_runtime_suspend(struct device *, pm_message_t);
|
||||
extern void dpm_runtime_resume(struct device *);
|
||||
|
||||
#else /* CONFIG_PM */
|
||||
|
||||
|
||||
@@ -82,14 +79,4 @@ static inline void device_pm_remove(struct device * dev)
|
||||
|
||||
}
|
||||
|
||||
static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dpm_runtime_resume(struct device * dev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,6 +36,7 @@ void dpm_runtime_resume(struct device * dev)
|
||||
runtime_resume(dev);
|
||||
up(&dpm_sem);
|
||||
}
|
||||
EXPORT_SYMBOL(dpm_runtime_resume);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1512,7 +1512,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
|
||||
scmd->nsg = 1;
|
||||
sg = &scmd->sgv[0];
|
||||
sg->page = virt_to_page(sc->top_sense);
|
||||
sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1);
|
||||
sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1);
|
||||
sg->length = UB_SENSE_SIZE;
|
||||
scmd->len = UB_SENSE_SIZE;
|
||||
scmd->lun = cmd->lun;
|
||||
@@ -1891,7 +1891,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
|
||||
cmd->nsg = 1;
|
||||
sg = &cmd->sgv[0];
|
||||
sg->page = virt_to_page(p);
|
||||
sg->offset = (unsigned int)p & (PAGE_SIZE-1);
|
||||
sg->offset = (unsigned long)p & (PAGE_SIZE-1);
|
||||
sg->length = 8;
|
||||
cmd->len = 8;
|
||||
cmd->lun = lun;
|
||||
|
||||
+3
-250
@@ -7,6 +7,9 @@
|
||||
*
|
||||
* Copyright (c) 1999 Martin Mares <mj@ucw.cz>
|
||||
*
|
||||
* Init/reset quirks for USB host controllers should be in the
|
||||
* USB quirks file, where their drivers can access reuse it.
|
||||
*
|
||||
* The bridge optimization stuff has been removed. If you really
|
||||
* have a silly BIOS which is unable to set your host bridge right,
|
||||
* use the PowerTweak utility (see http://powertweak.sourceforge.net).
|
||||
@@ -644,28 +647,6 @@ static void quirk_via_irq(struct pci_dev *dev)
|
||||
}
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
|
||||
|
||||
/*
|
||||
* PIIX3 USB: We have to disable USB interrupts that are
|
||||
* hardwired to PIRQD# and may be shared with an
|
||||
* external device.
|
||||
*
|
||||
* Legacy Support Register (LEGSUP):
|
||||
* bit13: USB PIRQ Enable (USBPIRQDEN),
|
||||
* bit4: Trap/SMI On IRQ Enable (USBSMIEN).
|
||||
*
|
||||
* We mask out all r/wc bits, too.
|
||||
*/
|
||||
static void __devinit quirk_piix3_usb(struct pci_dev *dev)
|
||||
{
|
||||
u16 legsup;
|
||||
|
||||
pci_read_config_word(dev, 0xc0, &legsup);
|
||||
legsup &= 0x50ef;
|
||||
pci_write_config_word(dev, 0xc0, legsup);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb );
|
||||
|
||||
/*
|
||||
* VIA VT82C598 has its device ID settable and many BIOSes
|
||||
* set it to the ID of VT82C597 for backward compatibility.
|
||||
@@ -1039,234 +1020,6 @@ static void __init quirk_sis_96x_smbus(struct pci_dev *dev)
|
||||
pci_read_config_byte(dev, 0x77, &val);
|
||||
}
|
||||
|
||||
|
||||
#define UHCI_USBLEGSUP 0xc0 /* legacy support */
|
||||
#define UHCI_USBCMD 0 /* command register */
|
||||
#define UHCI_USBSTS 2 /* status register */
|
||||
#define UHCI_USBINTR 4 /* interrupt register */
|
||||
#define UHCI_USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
|
||||
#define UHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */
|
||||
#define UHCI_USBCMD_GRESET (1 << 2) /* Global reset */
|
||||
#define UHCI_USBCMD_CONFIGURE (1 << 6) /* config semaphore */
|
||||
#define UHCI_USBSTS_HALTED (1 << 5) /* HCHalted bit */
|
||||
|
||||
#define OHCI_CONTROL 0x04
|
||||
#define OHCI_CMDSTATUS 0x08
|
||||
#define OHCI_INTRSTATUS 0x0c
|
||||
#define OHCI_INTRENABLE 0x10
|
||||
#define OHCI_INTRDISABLE 0x14
|
||||
#define OHCI_OCR (1 << 3) /* ownership change request */
|
||||
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
|
||||
#define OHCI_INTR_OC (1 << 30) /* ownership change */
|
||||
|
||||
#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */
|
||||
#define EHCI_USBCMD 0 /* command register */
|
||||
#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */
|
||||
#define EHCI_USBSTS 4 /* status register */
|
||||
#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */
|
||||
#define EHCI_USBINTR 8 /* interrupt register */
|
||||
#define EHCI_USBLEGSUP 0 /* legacy support register */
|
||||
#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */
|
||||
#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */
|
||||
#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
|
||||
#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */
|
||||
|
||||
int usb_early_handoff __devinitdata = 0;
|
||||
static int __init usb_handoff_early(char *str)
|
||||
{
|
||||
usb_early_handoff = 1;
|
||||
return 0;
|
||||
}
|
||||
__setup("usb-handoff", usb_handoff_early);
|
||||
|
||||
static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned long base = 0;
|
||||
int wait_time, delta;
|
||||
u16 val, sts;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PCI_ROM_RESOURCE; i++)
|
||||
if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
|
||||
base = pci_resource_start(pdev, i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!base)
|
||||
return;
|
||||
|
||||
/*
|
||||
* stop controller
|
||||
*/
|
||||
sts = inw(base + UHCI_USBSTS);
|
||||
val = inw(base + UHCI_USBCMD);
|
||||
val &= ~(u16)(UHCI_USBCMD_RUN | UHCI_USBCMD_CONFIGURE);
|
||||
outw(val, base + UHCI_USBCMD);
|
||||
|
||||
/*
|
||||
* wait while it stops if it was running
|
||||
*/
|
||||
if ((sts & UHCI_USBSTS_HALTED) == 0)
|
||||
{
|
||||
wait_time = 1000;
|
||||
delta = 100;
|
||||
|
||||
do {
|
||||
outw(0x1f, base + UHCI_USBSTS);
|
||||
udelay(delta);
|
||||
wait_time -= delta;
|
||||
val = inw(base + UHCI_USBSTS);
|
||||
if (val & UHCI_USBSTS_HALTED)
|
||||
break;
|
||||
} while (wait_time > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* disable interrupts & legacy support
|
||||
*/
|
||||
outw(0, base + UHCI_USBINTR);
|
||||
outw(0x1f, base + UHCI_USBSTS);
|
||||
pci_read_config_word(pdev, UHCI_USBLEGSUP, &val);
|
||||
if (val & 0xbf)
|
||||
pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
|
||||
|
||||
}
|
||||
|
||||
static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
||||
{
|
||||
void __iomem *base;
|
||||
int wait_time;
|
||||
|
||||
base = ioremap_nocache(pci_resource_start(pdev, 0),
|
||||
pci_resource_len(pdev, 0));
|
||||
if (base == NULL) return;
|
||||
|
||||
if (readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
|
||||
wait_time = 500; /* 0.5 seconds */
|
||||
writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
|
||||
writel(OHCI_OCR, base + OHCI_CMDSTATUS);
|
||||
while (wait_time > 0 &&
|
||||
readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
|
||||
wait_time -= 10;
|
||||
msleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* disable interrupts
|
||||
*/
|
||||
writel(~(u32)0, base + OHCI_INTRDISABLE);
|
||||
writel(~(u32)0, base + OHCI_INTRSTATUS);
|
||||
|
||||
iounmap(base);
|
||||
}
|
||||
|
||||
static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
|
||||
{
|
||||
int wait_time, delta;
|
||||
void __iomem *base, *op_reg_base;
|
||||
u32 hcc_params, val, temp;
|
||||
u8 cap_length;
|
||||
|
||||
base = ioremap_nocache(pci_resource_start(pdev, 0),
|
||||
pci_resource_len(pdev, 0));
|
||||
if (base == NULL) return;
|
||||
|
||||
cap_length = readb(base);
|
||||
op_reg_base = base + cap_length;
|
||||
hcc_params = readl(base + EHCI_HCC_PARAMS);
|
||||
hcc_params = (hcc_params >> 8) & 0xff;
|
||||
if (hcc_params) {
|
||||
pci_read_config_dword(pdev,
|
||||
hcc_params + EHCI_USBLEGSUP,
|
||||
&val);
|
||||
if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
|
||||
/*
|
||||
* Ok, BIOS is in smm mode, try to hand off...
|
||||
*/
|
||||
pci_read_config_dword(pdev,
|
||||
hcc_params + EHCI_USBLEGCTLSTS,
|
||||
&temp);
|
||||
pci_write_config_dword(pdev,
|
||||
hcc_params + EHCI_USBLEGCTLSTS,
|
||||
temp | EHCI_USBLEGCTLSTS_SOOE);
|
||||
val |= EHCI_USBLEGSUP_OS;
|
||||
pci_write_config_dword(pdev,
|
||||
hcc_params + EHCI_USBLEGSUP,
|
||||
val);
|
||||
|
||||
wait_time = 500;
|
||||
do {
|
||||
msleep(10);
|
||||
wait_time -= 10;
|
||||
pci_read_config_dword(pdev,
|
||||
hcc_params + EHCI_USBLEGSUP,
|
||||
&val);
|
||||
} while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
|
||||
if (!wait_time) {
|
||||
/*
|
||||
* well, possibly buggy BIOS...
|
||||
*/
|
||||
printk(KERN_WARNING "EHCI early BIOS handoff "
|
||||
"failed (BIOS bug ?)\n");
|
||||
pci_write_config_dword(pdev,
|
||||
hcc_params + EHCI_USBLEGSUP,
|
||||
EHCI_USBLEGSUP_OS);
|
||||
pci_write_config_dword(pdev,
|
||||
hcc_params + EHCI_USBLEGCTLSTS,
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* halt EHCI & disable its interrupts in any case
|
||||
*/
|
||||
val = readl(op_reg_base + EHCI_USBSTS);
|
||||
if ((val & EHCI_USBSTS_HALTED) == 0) {
|
||||
val = readl(op_reg_base + EHCI_USBCMD);
|
||||
val &= ~EHCI_USBCMD_RUN;
|
||||
writel(val, op_reg_base + EHCI_USBCMD);
|
||||
|
||||
wait_time = 2000;
|
||||
delta = 100;
|
||||
do {
|
||||
writel(0x3f, op_reg_base + EHCI_USBSTS);
|
||||
udelay(delta);
|
||||
wait_time -= delta;
|
||||
val = readl(op_reg_base + EHCI_USBSTS);
|
||||
if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
|
||||
break;
|
||||
}
|
||||
} while (wait_time > 0);
|
||||
}
|
||||
writel(0, op_reg_base + EHCI_USBINTR);
|
||||
writel(0x3f, op_reg_base + EHCI_USBSTS);
|
||||
|
||||
iounmap(base);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
|
||||
{
|
||||
if (!usb_early_handoff)
|
||||
return;
|
||||
|
||||
if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x00)) { /* UHCI */
|
||||
quirk_usb_handoff_uhci(pdev);
|
||||
} else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) { /* OHCI */
|
||||
quirk_usb_handoff_ohci(pdev);
|
||||
} else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x20)) { /* EHCI */
|
||||
quirk_usb_disable_ehci(pdev);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
|
||||
|
||||
/*
|
||||
* ... This is further complicated by the fact that some SiS96x south
|
||||
* bridges pretend to be 85C503/5513 instead. In that case see if we
|
||||
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB) += core/
|
||||
|
||||
obj-$(CONFIG_USB_MON) += mon/
|
||||
|
||||
obj-$(CONFIG_PCI) += host/
|
||||
obj-$(CONFIG_USB_EHCI_HCD) += host/
|
||||
obj-$(CONFIG_USB_ISP116X_HCD) += host/
|
||||
obj-$(CONFIG_USB_OHCI_HCD) += host/
|
||||
@@ -17,7 +18,6 @@ obj-$(CONFIG_ETRAX_USB_HOST) += host/
|
||||
|
||||
obj-$(CONFIG_USB_ACM) += class/
|
||||
obj-$(CONFIG_USB_AUDIO) += class/
|
||||
obj-$(CONFIG_USB_BLUETOOTH_TTY) += class/
|
||||
obj-$(CONFIG_USB_MIDI) += class/
|
||||
obj-$(CONFIG_USB_PRINTER) += class/
|
||||
|
||||
|
||||
@@ -28,29 +28,6 @@ config USB_AUDIO
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called audio.
|
||||
|
||||
comment "USB Bluetooth TTY can only be used with disabled Bluetooth subsystem"
|
||||
depends on USB && BT
|
||||
|
||||
config USB_BLUETOOTH_TTY
|
||||
tristate "USB Bluetooth TTY support"
|
||||
depends on USB && BT=n
|
||||
---help---
|
||||
This driver implements a nonstandard tty interface to a Bluetooth
|
||||
device that can be used only by specialized Bluetooth HCI software.
|
||||
|
||||
Say Y here if you want to use OpenBT Bluetooth stack (available
|
||||
at <http://developer.axis.com/software>), or other TTY based
|
||||
Bluetooth stacks, and want to connect a USB Bluetooth device
|
||||
to your computer's USB port.
|
||||
|
||||
Do *not* enable this driver if you want to use generic Linux
|
||||
Bluetooth support.
|
||||
|
||||
If in doubt, say N here.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called bluetty.
|
||||
|
||||
config USB_MIDI
|
||||
tristate "USB MIDI support"
|
||||
depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER
|
||||
|
||||
@@ -5,6 +5,5 @@
|
||||
|
||||
obj-$(CONFIG_USB_ACM) += cdc-acm.o
|
||||
obj-$(CONFIG_USB_AUDIO) += audio.o
|
||||
obj-$(CONFIG_USB_BLUETOOTH_TTY) += bluetty.o
|
||||
obj-$(CONFIG_USB_MIDI) += usb-midi.o
|
||||
obj-$(CONFIG_USB_PRINTER) += usblp.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -827,11 +827,10 @@ skip_normal_probe:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
|
||||
dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
|
||||
if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
|
||||
dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
|
||||
goto alloc_fail;
|
||||
}
|
||||
memset(acm, 0, sizeof(struct acm));
|
||||
|
||||
ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
|
||||
readsize = le16_to_cpu(epread->wMaxPacketSize);
|
||||
|
||||
@@ -844,9 +844,8 @@ static struct file_operations usblp_fops = {
|
||||
};
|
||||
|
||||
static struct usb_class_driver usblp_class = {
|
||||
.name = "usb/lp%d",
|
||||
.name = "lp%d",
|
||||
.fops = &usblp_fops,
|
||||
.mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
|
||||
.minor_base = USBLP_MINOR_BASE,
|
||||
};
|
||||
|
||||
|
||||
@@ -61,14 +61,17 @@ config USB_DYNAMIC_MINORS
|
||||
If you are unsure about this, say N here.
|
||||
|
||||
config USB_SUSPEND
|
||||
bool "USB suspend/resume (EXPERIMENTAL)"
|
||||
bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
|
||||
depends on USB && PM && EXPERIMENTAL
|
||||
help
|
||||
If you say Y here, you can use driver calls or the sysfs
|
||||
"power/state" file to suspend or resume individual USB
|
||||
peripherals. There are many related features, such as
|
||||
remote wakeup and driver-specific suspend processing, that
|
||||
may not yet work as expected.
|
||||
peripherals.
|
||||
|
||||
Also, USB "remote wakeup" signaling is supported, whereby some
|
||||
USB devices (like keyboards and network adapters) can wake up
|
||||
their parent hub. That wakeup cascades up the USB tree, and
|
||||
could wake the system from states like suspend-to-RAM.
|
||||
|
||||
If you are unsure about this, say N here.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
usbcore-objs := usb.o hub.o hcd.o urb.o message.o \
|
||||
config.o file.o buffer.o sysfs.o devio.o
|
||||
config.o file.o buffer.o sysfs.o devio.o notify.o
|
||||
|
||||
ifeq ($(CONFIG_PCI),y)
|
||||
usbcore-objs += hcd-pci.o
|
||||
|
||||
+10
-12
@@ -112,8 +112,12 @@ void usb_release_interface_cache(struct kref *ref)
|
||||
struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
|
||||
int j;
|
||||
|
||||
for (j = 0; j < intfc->num_altsetting; j++)
|
||||
kfree(intfc->altsetting[j].endpoint);
|
||||
for (j = 0; j < intfc->num_altsetting; j++) {
|
||||
struct usb_host_interface *alt = &intfc->altsetting[j];
|
||||
|
||||
kfree(alt->endpoint);
|
||||
kfree(alt->string);
|
||||
}
|
||||
kfree(intfc);
|
||||
}
|
||||
|
||||
@@ -188,10 +192,9 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
|
||||
}
|
||||
|
||||
len = sizeof(struct usb_host_endpoint) * num_ep;
|
||||
alt->endpoint = kmalloc(len, GFP_KERNEL);
|
||||
alt->endpoint = kzalloc(len, GFP_KERNEL);
|
||||
if (!alt->endpoint)
|
||||
return -ENOMEM;
|
||||
memset(alt->endpoint, 0, len);
|
||||
|
||||
/* Parse all the endpoint descriptors */
|
||||
n = 0;
|
||||
@@ -353,10 +356,9 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
|
||||
}
|
||||
|
||||
len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
|
||||
config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL);
|
||||
config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
|
||||
if (!intfc)
|
||||
return -ENOMEM;
|
||||
memset(intfc, 0, len);
|
||||
kref_init(&intfc->ref);
|
||||
}
|
||||
|
||||
@@ -422,8 +424,6 @@ void usb_destroy_configuration(struct usb_device *dev)
|
||||
struct usb_host_config *cf = &dev->config[c];
|
||||
|
||||
kfree(cf->string);
|
||||
cf->string = NULL;
|
||||
|
||||
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
|
||||
if (cf->intf_cache[i])
|
||||
kref_put(&cf->intf_cache[i]->ref,
|
||||
@@ -459,16 +459,14 @@ int usb_get_configuration(struct usb_device *dev)
|
||||
}
|
||||
|
||||
length = ncfg * sizeof(struct usb_host_config);
|
||||
dev->config = kmalloc(length, GFP_KERNEL);
|
||||
dev->config = kzalloc(length, GFP_KERNEL);
|
||||
if (!dev->config)
|
||||
goto err2;
|
||||
memset(dev->config, 0, length);
|
||||
|
||||
length = ncfg * sizeof(char *);
|
||||
dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
|
||||
dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
|
||||
if (!dev->rawdescriptors)
|
||||
goto err2;
|
||||
memset(dev->rawdescriptors, 0, length);
|
||||
|
||||
buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
|
||||
+145
-45
@@ -46,6 +46,7 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/moduleparam.h>
|
||||
@@ -209,10 +210,10 @@ err:
|
||||
static struct async *alloc_async(unsigned int numisoframes)
|
||||
{
|
||||
unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
|
||||
struct async *as = kmalloc(assize, GFP_KERNEL);
|
||||
struct async *as = kzalloc(assize, GFP_KERNEL);
|
||||
|
||||
if (!as)
|
||||
return NULL;
|
||||
memset(as, 0, assize);
|
||||
as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
|
||||
if (!as->urb) {
|
||||
kfree(as);
|
||||
@@ -279,6 +280,28 @@ static inline struct async *async_getpending(struct dev_state *ps, void __user *
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void snoop_urb(struct urb *urb, void __user *userurb)
|
||||
{
|
||||
int j;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
|
||||
if (!usbfs_snoop)
|
||||
return;
|
||||
|
||||
if (urb->pipe & USB_DIR_IN)
|
||||
dev_info(&urb->dev->dev, "direction=IN\n");
|
||||
else
|
||||
dev_info(&urb->dev->dev, "direction=OUT\n");
|
||||
dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
|
||||
dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
|
||||
urb->transfer_buffer_length);
|
||||
dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
|
||||
dev_info(&urb->dev->dev, "data: ");
|
||||
for (j = 0; j < urb->transfer_buffer_length; ++j)
|
||||
printk ("%02x ", data[j]);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static void async_completed(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct async *as = (struct async *)urb->context;
|
||||
@@ -296,7 +319,9 @@ static void async_completed(struct urb *urb, struct pt_regs *regs)
|
||||
kill_proc_info_as_uid(as->signr, &sinfo, as->pid, as->uid,
|
||||
as->euid);
|
||||
}
|
||||
wake_up(&ps->wait);
|
||||
snoop(&urb->dev->dev, "urb complete\n");
|
||||
snoop_urb(urb, as->userurb);
|
||||
wake_up(&ps->wait);
|
||||
}
|
||||
|
||||
static void destroy_async (struct dev_state *ps, struct list_head *list)
|
||||
@@ -493,6 +518,23 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct usb_device *usbdev_lookup_minor(int minor)
|
||||
{
|
||||
struct class_device *class_dev;
|
||||
struct usb_device *dev = NULL;
|
||||
|
||||
down(&usb_device_class->sem);
|
||||
list_for_each_entry(class_dev, &usb_device_class->children, node) {
|
||||
if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
|
||||
dev = class_dev->class_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&usb_device_class->sem);
|
||||
|
||||
return dev;
|
||||
};
|
||||
|
||||
/*
|
||||
* file operations
|
||||
*/
|
||||
@@ -601,7 +643,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
||||
if (usbfs_snoop) {
|
||||
dev_info(&dev->dev, "control read: data ");
|
||||
for (j = 0; j < i; ++j)
|
||||
printk ("%02x ", (unsigned char)(tbuf)[j]);
|
||||
printk("%02x ", (unsigned char)(tbuf)[j]);
|
||||
printk("\n");
|
||||
}
|
||||
if (copy_to_user(ctrl.data, tbuf, i)) {
|
||||
@@ -624,7 +666,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
||||
if (usbfs_snoop) {
|
||||
dev_info(&dev->dev, "control write: data: ");
|
||||
for (j = 0; j < ctrl.wLength; ++j)
|
||||
printk ("%02x ", (unsigned char)(tbuf)[j]);
|
||||
printk("%02x ", (unsigned char)(tbuf)[j]);
|
||||
printk("\n");
|
||||
}
|
||||
usb_unlock_device(dev);
|
||||
@@ -649,7 +691,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
||||
unsigned int tmo, len1, pipe;
|
||||
int len2;
|
||||
unsigned char *tbuf;
|
||||
int i, ret;
|
||||
int i, j, ret;
|
||||
|
||||
if (copy_from_user(&bulk, arg, sizeof(bulk)))
|
||||
return -EFAULT;
|
||||
@@ -674,10 +716,18 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
||||
kfree(tbuf);
|
||||
return -EINVAL;
|
||||
}
|
||||
snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n",
|
||||
bulk.len, bulk.timeout);
|
||||
usb_unlock_device(dev);
|
||||
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
|
||||
usb_lock_device(dev);
|
||||
if (!i && len2) {
|
||||
if (usbfs_snoop) {
|
||||
dev_info(&dev->dev, "bulk read: data ");
|
||||
for (j = 0; j < len2; ++j)
|
||||
printk("%02x ", (unsigned char)(tbuf)[j]);
|
||||
printk("\n");
|
||||
}
|
||||
if (copy_to_user(bulk.data, tbuf, len2)) {
|
||||
kfree(tbuf);
|
||||
return -EFAULT;
|
||||
@@ -690,6 +740,14 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n",
|
||||
bulk.len, bulk.timeout);
|
||||
if (usbfs_snoop) {
|
||||
dev_info(&dev->dev, "bulk write: data: ");
|
||||
for (j = 0; j < len1; ++j)
|
||||
printk("%02x ", (unsigned char)(tbuf)[j]);
|
||||
printk("\n");
|
||||
}
|
||||
usb_unlock_device(dev);
|
||||
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
|
||||
usb_lock_device(dev);
|
||||
@@ -835,7 +893,6 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
|
||||
void __user *arg)
|
||||
@@ -896,6 +953,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
kfree(dr);
|
||||
return -EFAULT;
|
||||
}
|
||||
snoop(&ps->dev->dev, "control urb\n");
|
||||
break;
|
||||
|
||||
case USBDEVFS_URB_TYPE_BULK:
|
||||
@@ -910,6 +968,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
return -EINVAL;
|
||||
if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
|
||||
return -EFAULT;
|
||||
snoop(&ps->dev->dev, "bulk urb\n");
|
||||
break;
|
||||
|
||||
case USBDEVFS_URB_TYPE_ISO:
|
||||
@@ -939,6 +998,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
return -EINVAL;
|
||||
}
|
||||
uurb->buffer_length = totlen;
|
||||
snoop(&ps->dev->dev, "iso urb\n");
|
||||
break;
|
||||
|
||||
case USBDEVFS_URB_TYPE_INTERRUPT:
|
||||
@@ -954,6 +1014,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
return -EINVAL;
|
||||
if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
|
||||
return -EFAULT;
|
||||
snoop(&ps->dev->dev, "interrupt urb\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1003,6 +1064,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
snoop(&as->urb->dev->dev, "submit urb\n");
|
||||
snoop_urb(as->urb, as->userurb);
|
||||
async_newpending(as);
|
||||
if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
|
||||
dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);
|
||||
@@ -1238,23 +1301,20 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
||||
static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
|
||||
{
|
||||
struct usbdevfs_ioctl ctrl;
|
||||
int size;
|
||||
void *buf = NULL;
|
||||
int retval = 0;
|
||||
struct usb_interface *intf = NULL;
|
||||
struct usb_driver *driver = NULL;
|
||||
|
||||
/* get input parameters and alloc buffer */
|
||||
if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
|
||||
return -EFAULT;
|
||||
if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
|
||||
/* alloc buffer */
|
||||
if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) {
|
||||
if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {
|
||||
if (copy_from_user (buf, ctrl.data, size)) {
|
||||
if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
|
||||
if (copy_from_user (buf, ctl->data, size)) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
@@ -1270,9 +1330,9 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
||||
|
||||
if (ps->dev->state != USB_STATE_CONFIGURED)
|
||||
retval = -EHOSTUNREACH;
|
||||
else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
|
||||
else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno)))
|
||||
retval = -EINVAL;
|
||||
else switch (ctrl.ioctl_code) {
|
||||
else switch (ctl->ioctl_code) {
|
||||
|
||||
/* disconnect kernel driver from interface */
|
||||
case USBDEVFS_DISCONNECT:
|
||||
@@ -1304,7 +1364,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
||||
if (driver == NULL || driver->ioctl == NULL) {
|
||||
retval = -ENOTTY;
|
||||
} else {
|
||||
retval = driver->ioctl (intf, ctrl.ioctl_code, buf);
|
||||
retval = driver->ioctl (intf, ctl->ioctl_code, buf);
|
||||
if (retval == -ENOIOCTLCMD)
|
||||
retval = -ENOTTY;
|
||||
}
|
||||
@@ -1313,15 +1373,42 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
||||
|
||||
/* cleanup and return */
|
||||
if (retval >= 0
|
||||
&& (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
|
||||
&& (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
|
||||
&& size > 0
|
||||
&& copy_to_user (ctrl.data, buf, size) != 0)
|
||||
&& copy_to_user (ctl->data, buf, size) != 0)
|
||||
retval = -EFAULT;
|
||||
|
||||
kfree(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int proc_ioctl_default(struct dev_state *ps, void __user *arg)
|
||||
{
|
||||
struct usbdevfs_ioctl ctrl;
|
||||
|
||||
if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
|
||||
return -EFAULT;
|
||||
return proc_ioctl(ps, &ctrl);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int proc_ioctl_compat(struct dev_state *ps, void __user *arg)
|
||||
{
|
||||
struct usbdevfs_ioctl32 __user *uioc;
|
||||
struct usbdevfs_ioctl ctrl;
|
||||
u32 udata;
|
||||
|
||||
uioc = compat_ptr(arg);
|
||||
if (get_user(ctrl.ifno, &uioc->ifno) ||
|
||||
get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
|
||||
__get_user(udata, &uioc->data))
|
||||
return -EFAULT;
|
||||
ctrl.data = compat_ptr(udata);
|
||||
|
||||
return proc_ioctl(ps, &ctrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NOTE: All requests here that have interface numbers as parameters
|
||||
* are assuming that somehow the configuration has been prevented from
|
||||
@@ -1422,6 +1509,10 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
|
||||
ret = proc_reapurbnonblock_compat(ps, p);
|
||||
break;
|
||||
|
||||
case USBDEVFS_IOCTL32:
|
||||
snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
|
||||
ret = proc_ioctl_compat(ps, p);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case USBDEVFS_DISCARDURB:
|
||||
@@ -1456,7 +1547,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
|
||||
|
||||
case USBDEVFS_IOCTL:
|
||||
snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
|
||||
ret = proc_ioctl(ps, p);
|
||||
ret = proc_ioctl_default(ps, p);
|
||||
break;
|
||||
}
|
||||
usb_unlock_device(dev);
|
||||
@@ -1488,24 +1579,7 @@ struct file_operations usbfs_device_file_operations = {
|
||||
.release = usbdev_release,
|
||||
};
|
||||
|
||||
struct usb_device *usbdev_lookup_minor(int minor)
|
||||
{
|
||||
struct class_device *class_dev;
|
||||
struct usb_device *dev = NULL;
|
||||
|
||||
down(&usb_device_class->sem);
|
||||
list_for_each_entry(class_dev, &usb_device_class->children, node) {
|
||||
if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
|
||||
dev = class_dev->class_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&usb_device_class->sem);
|
||||
|
||||
return dev;
|
||||
};
|
||||
|
||||
void usbdev_add(struct usb_device *dev)
|
||||
static void usbdev_add(struct usb_device *dev)
|
||||
{
|
||||
int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
|
||||
|
||||
@@ -1516,11 +1590,29 @@ void usbdev_add(struct usb_device *dev)
|
||||
dev->class_dev->class_data = dev;
|
||||
}
|
||||
|
||||
void usbdev_remove(struct usb_device *dev)
|
||||
static void usbdev_remove(struct usb_device *dev)
|
||||
{
|
||||
class_device_unregister(dev->class_dev);
|
||||
}
|
||||
|
||||
static int usbdev_notify(struct notifier_block *self, unsigned long action,
|
||||
void *dev)
|
||||
{
|
||||
switch (action) {
|
||||
case USB_DEVICE_ADD:
|
||||
usbdev_add(dev);
|
||||
break;
|
||||
case USB_DEVICE_REMOVE:
|
||||
usbdev_remove(dev);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block usbdev_nb = {
|
||||
.notifier_call = usbdev_notify,
|
||||
};
|
||||
|
||||
static struct cdev usb_device_cdev = {
|
||||
.kobj = {.name = "usb_device", },
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1540,24 +1632,32 @@ int __init usbdev_init(void)
|
||||
retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
if (retval) {
|
||||
err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
|
||||
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
goto out;
|
||||
goto error_cdev;
|
||||
}
|
||||
usb_device_class = class_create(THIS_MODULE, "usb_device");
|
||||
if (IS_ERR(usb_device_class)) {
|
||||
err("unable to register usb_device class");
|
||||
retval = PTR_ERR(usb_device_class);
|
||||
usb_device_class = NULL;
|
||||
cdev_del(&usb_device_cdev);
|
||||
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
goto error_class;
|
||||
}
|
||||
|
||||
usb_register_notify(&usbdev_nb);
|
||||
|
||||
out:
|
||||
return retval;
|
||||
|
||||
error_class:
|
||||
usb_device_class = NULL;
|
||||
cdev_del(&usb_device_cdev);
|
||||
|
||||
error_cdev:
|
||||
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void usbdev_cleanup(void)
|
||||
{
|
||||
usb_unregister_notify(&usbdev_nb);
|
||||
class_destroy(usb_device_class);
|
||||
cdev_del(&usb_device_cdev);
|
||||
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user