diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 12:59:04 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 12:59:04 -0800 |
commit | 460223d21d960e420775ca4d11ddaa8389af4d25 (patch) | |
tree | c1e9d3e661180263f5e4ac72af85a151d3c183e7 /drivers/usb/misc | |
parent | 255f0385c8e0d6b9005c0e09fffb5bd852f3b506 (diff) | |
parent | ed077bb714816e942ea9b740156659a28a34112f (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/Kconfig | 11 | ||||
-rw-r--r-- | drivers/usb/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/misc/berry_charge.c | 140 |
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"); |