summaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-19 12:59:04 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-19 12:59:04 -0800
commit460223d21d960e420775ca4d11ddaa8389af4d25 (patch)
treec1e9d3e661180263f5e4ac72af85a151d3c183e7 /drivers/usb/misc
parent255f0385c8e0d6b9005c0e09fffb5bd852f3b506 (diff)
parented077bb714816e942ea9b740156659a28a34112f (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (39 commits) USB: at91-ohci, handle extra at91sam9261 ahb clock USB: another id for cp2101 driver USB: ueagle-atm.c needs sched.h USB: at91_udc, shrink runtime footprint usbnet: add missing Kconfig for KC2190 cables usbnet: init fault (oops) cleanup, whitespace fixes usbnet: recognize SiteCom CN-124 usb: Remove Airprime device from option.c USB: change __init to __devinit for isp116x_probe USB: ps3: don't call ps3_system_bus_driver_register on other platforms USB: hid-core.c: Removes GTCO CalComp Interwrite IPanel PIDs from blacklist USB: kernel-doc fixes USB: quirky device for cdc-acm USB: cdc-acm: fix incorrect throtteling, make set_control optional USB: unconfigure devices which have config 0 USB: make usb_iso_packet_descriptor.status signed USB: fix g_serial small error USB: use __u32 rather than u32 in userspace ioctls in usbdevice_fs.h USB Storage: US_FL_IGNORE_RESIDUE needed for Aiptek MP3 Player USB: Fix misspelled "USBNET_MII" kernel config option. ...
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r--drivers/usb/misc/Kconfig11
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/berry_charge.c140
3 files changed, 152 insertions, 0 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a74bf8617e7..4907e8b8007 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -88,6 +88,17 @@ config USB_LCD
To compile this driver as a module, choose M here: the
module will be called usblcd.
+config USB_BERRY_CHARGE
+ tristate "USB BlackBerry recharge support"
+ depends on USB
+ help
+ Say Y here if you want to connect a BlackBerry device to your
+ computer's USB port and have it automatically switch to "recharge"
+ mode.
+
+ To compile this driver as a module, choose M here: the
+ module will be called berry_charge.
+
config USB_LED
tristate "USB LED driver support"
depends on USB
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 2cba07d3197..dac2d5b7156 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_USB_ADUTUX) += adutux.o
obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
+obj-$(CONFIG_USB_BERRY_CHARGE) += berry_charge.o
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
obj-$(CONFIG_USB_EMI26) += emi26.o
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
new file mode 100644
index 00000000000..60893c6c822
--- /dev/null
+++ b/drivers/usb/misc/berry_charge.c
@@ -0,0 +1,140 @@
+/*
+ * USB BlackBerry charging module
+ *
+ * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ * Information on how to switch configs was taken by the bcharge.cc file
+ * created by the barry.sf.net project.
+ *
+ * bcharge.cc has the following copyright:
+ * Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/)
+ * and is released under the GPLv2.
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#define RIM_VENDOR 0x0fca
+#define BLACKBERRY 0x0001
+
+static int debug;
+
+#ifdef dbg
+#undef dbg
+#endif
+#define dbg(dev, format, arg...) \
+ if (debug) \
+ dev_printk(KERN_DEBUG , dev , format , ## arg)
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+ { }, /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int magic_charge(struct usb_device *udev)
+{
+ char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+ int retval;
+
+ if (!dummy_buffer)
+ return -ENOMEM;
+
+ /* send two magic commands and then set the configuration. The device
+ * will then reset itself with the new power usage and should start
+ * charging. */
+
+ /* Note, with testing, it only seems that the first message is really
+ * needed (at least for the 8700c), but to be safe, we emulate what
+ * other operating systems seem to be sending to their device. We
+ * really need to get some specs for this device to be sure about what
+ * is going on here.
+ */
+ dbg(&udev->dev, "Sending first magic command\n");
+ retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100);
+ if (retval != 2) {
+ dev_err(&udev->dev, "First magic command failed: %d.\n",
+ retval);
+ return retval;
+ }
+
+ dbg(&udev->dev, "Sending first magic command\n");
+ retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
+ if (retval != 0) {
+ dev_err(&udev->dev, "Second magic command failed: %d.\n",
+ retval);
+ return retval;
+ }
+
+ dbg(&udev->dev, "Calling set_configuration\n");
+ retval = usb_driver_set_configuration(udev, 1);
+ if (retval)
+ dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+ return retval;
+}
+
+static int berry_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ dbg(&udev->dev, "Power is set to %dmA\n",
+ udev->actconfig->desc.bMaxPower * 2);
+
+ /* check the power usage so we don't try to enable something that is
+ * already enabled */
+ if ((udev->actconfig->desc.bMaxPower * 2) == 500) {
+ dbg(&udev->dev, "device is already charging, power is "
+ "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2);
+ return -ENODEV;
+ }
+
+ /* turn the power on */
+ magic_charge(udev);
+
+ /* we don't really want to bind to the device, userspace programs can
+ * handle the syncing just fine, so get outta here. */
+ return -ENODEV;
+}
+
+static void berry_disconnect(struct usb_interface *intf)
+{
+}
+
+static struct usb_driver berry_driver = {
+ .name = "berry_charge",
+ .probe = berry_probe,
+ .disconnect = berry_disconnect,
+ .id_table = id_table,
+};
+
+static int __init berry_init(void)
+{
+ return usb_register(&berry_driver);
+}
+
+static void __exit berry_exit(void)
+{
+ usb_deregister(&berry_driver);
+}
+
+module_init(berry_init);
+module_exit(berry_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");