Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26-rc5 178 lines 5.0 kB view raw
1/* 2 * USB BlackBerry charging module 3 * 4 * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.de> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2. 9 * 10 * Information on how to switch configs was taken by the bcharge.cc file 11 * created by the barry.sf.net project. 12 * 13 * bcharge.cc has the following copyright: 14 * Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/) 15 * and is released under the GPLv2. 16 * 17 * 18 */ 19 20#include <linux/kernel.h> 21#include <linux/errno.h> 22#include <linux/init.h> 23#include <linux/slab.h> 24#include <linux/module.h> 25#include <linux/usb.h> 26 27#define RIM_VENDOR 0x0fca 28#define BLACKBERRY 0x0001 29#define BLACKBERRY_PEARL_DUAL 0x0004 30#define BLACKBERRY_PEARL 0x0006 31 32static int debug; 33static int pearl_dual_mode = 1; 34 35#ifdef dbg 36#undef dbg 37#endif 38#define dbg(dev, format, arg...) \ 39 if (debug) \ 40 dev_printk(KERN_DEBUG , dev , format , ## arg) 41 42static struct usb_device_id id_table [] = { 43 { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, 44 { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) }, 45 { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) }, 46 { }, /* Terminating entry */ 47}; 48MODULE_DEVICE_TABLE(usb, id_table); 49 50static int magic_charge(struct usb_device *udev) 51{ 52 char *dummy_buffer = kzalloc(2, GFP_KERNEL); 53 int retval; 54 55 if (!dummy_buffer) 56 return -ENOMEM; 57 58 /* send two magic commands and then set the configuration. The device 59 * will then reset itself with the new power usage and should start 60 * charging. */ 61 62 /* Note, with testing, it only seems that the first message is really 63 * needed (at least for the 8700c), but to be safe, we emulate what 64 * other operating systems seem to be sending to their device. We 65 * really need to get some specs for this device to be sure about what 66 * is going on here. 67 */ 68 dbg(&udev->dev, "Sending first magic command\n"); 69 retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 70 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100); 71 if (retval != 2) { 72 dev_err(&udev->dev, "First magic command failed: %d.\n", 73 retval); 74 goto exit; 75 } 76 77 dbg(&udev->dev, "Sending second magic command\n"); 78 retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 79 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100); 80 if (retval != 0) { 81 dev_err(&udev->dev, "Second magic command failed: %d.\n", 82 retval); 83 goto exit; 84 } 85 86 dbg(&udev->dev, "Calling set_configuration\n"); 87 retval = usb_driver_set_configuration(udev, 1); 88 if (retval) 89 dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); 90 91exit: 92 kfree(dummy_buffer); 93 return retval; 94} 95 96static int magic_dual_mode(struct usb_device *udev) 97{ 98 char *dummy_buffer = kzalloc(2, GFP_KERNEL); 99 int retval; 100 101 if (!dummy_buffer) 102 return -ENOMEM; 103 104 /* send magic command so that the Blackberry Pearl device exposes 105 * two interfaces: both the USB mass-storage one and one which can 106 * be used for database access. */ 107 dbg(&udev->dev, "Sending magic pearl command\n"); 108 retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 109 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100); 110 dbg(&udev->dev, "Magic pearl command returned %d\n", retval); 111 112 dbg(&udev->dev, "Calling set_configuration\n"); 113 retval = usb_driver_set_configuration(udev, 1); 114 if (retval) 115 dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); 116 117 kfree(dummy_buffer); 118 return retval; 119} 120 121static int berry_probe(struct usb_interface *intf, 122 const struct usb_device_id *id) 123{ 124 struct usb_device *udev = interface_to_usbdev(intf); 125 126 dbg(&udev->dev, "Power is set to %dmA\n", 127 udev->actconfig->desc.bMaxPower * 2); 128 129 /* check the power usage so we don't try to enable something that is 130 * already enabled */ 131 if ((udev->actconfig->desc.bMaxPower * 2) == 500) { 132 dbg(&udev->dev, "device is already charging, power is " 133 "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2); 134 return -ENODEV; 135 } 136 137 /* turn the power on */ 138 magic_charge(udev); 139 140 if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) && 141 (pearl_dual_mode)) 142 magic_dual_mode(udev); 143 144 /* we don't really want to bind to the device, userspace programs can 145 * handle the syncing just fine, so get outta here. */ 146 return -ENODEV; 147} 148 149static void berry_disconnect(struct usb_interface *intf) 150{ 151} 152 153static struct usb_driver berry_driver = { 154 .name = "berry_charge", 155 .probe = berry_probe, 156 .disconnect = berry_disconnect, 157 .id_table = id_table, 158}; 159 160static int __init berry_init(void) 161{ 162 return usb_register(&berry_driver); 163} 164 165static void __exit berry_exit(void) 166{ 167 usb_deregister(&berry_driver); 168} 169 170module_init(berry_init); 171module_exit(berry_exit); 172 173MODULE_LICENSE("GPL"); 174MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); 175module_param(debug, bool, S_IRUGO | S_IWUSR); 176MODULE_PARM_DESC(debug, "Debug enabled or not"); 177module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR); 178MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode");