Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[sfrench/cifs-2.6.git] / drivers / usb / misc / berry_charge.c
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
30 static int debug;
31
32 #ifdef dbg
33 #undef dbg
34 #endif
35 #define dbg(dev, format, arg...)                                \
36         if (debug)                                              \
37                 dev_printk(KERN_DEBUG , dev , format , ## arg)
38
39 static struct usb_device_id id_table [] = {
40         { USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
41         { },                                    /* Terminating entry */
42 };
43 MODULE_DEVICE_TABLE(usb, id_table);
44
45 static int magic_charge(struct usb_device *udev)
46 {
47         char *dummy_buffer = kzalloc(2, GFP_KERNEL);
48         int retval;
49
50         if (!dummy_buffer)
51                 return -ENOMEM;
52
53         /* send two magic commands and then set the configuration.  The device
54          * will then reset itself with the new power usage and should start
55          * charging. */
56
57         /* Note, with testing, it only seems that the first message is really
58          * needed (at least for the 8700c), but to be safe, we emulate what
59          * other operating systems seem to be sending to their device.  We
60          * really need to get some specs for this device to be sure about what
61          * is going on here.
62          */
63         dbg(&udev->dev, "Sending first magic command\n");
64         retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
65                                  0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100);
66         if (retval != 2) {
67                 dev_err(&udev->dev, "First magic command failed: %d.\n",
68                         retval);
69                 return retval;
70         }
71
72         dbg(&udev->dev, "Sending first magic command\n");
73         retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
74                                  0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
75         if (retval != 0) {
76                 dev_err(&udev->dev, "Second magic command failed: %d.\n",
77                         retval);
78                 return retval;
79         }
80
81         dbg(&udev->dev, "Calling set_configuration\n");
82         retval = usb_driver_set_configuration(udev, 1);
83         if (retval)
84                 dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
85
86         return retval;
87 }
88
89 static int berry_probe(struct usb_interface *intf,
90                        const struct usb_device_id *id)
91 {
92         struct usb_device *udev = interface_to_usbdev(intf);
93
94         dbg(&udev->dev, "Power is set to %dmA\n",
95             udev->actconfig->desc.bMaxPower * 2);
96
97         /* check the power usage so we don't try to enable something that is
98          * already enabled */
99         if ((udev->actconfig->desc.bMaxPower * 2) == 500) {
100                 dbg(&udev->dev, "device is already charging, power is "
101                     "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2);
102                 return -ENODEV;
103         }
104
105         /* turn the power on */
106         magic_charge(udev);
107
108         /* we don't really want to bind to the device, userspace programs can
109          * handle the syncing just fine, so get outta here. */
110         return -ENODEV;
111 }
112
113 static void berry_disconnect(struct usb_interface *intf)
114 {
115 }
116
117 static struct usb_driver berry_driver = {
118         .name =         "berry_charge",
119         .probe =        berry_probe,
120         .disconnect =   berry_disconnect,
121         .id_table =     id_table,
122 };
123
124 static int __init berry_init(void)
125 {
126         return usb_register(&berry_driver);
127 }
128
129 static void __exit berry_exit(void)
130 {
131         usb_deregister(&berry_driver);
132 }
133
134 module_init(berry_init);
135 module_exit(berry_exit);
136
137 MODULE_LICENSE("GPL");
138 MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
139 module_param(debug, bool, S_IRUGO | S_IWUSR);
140 MODULE_PARM_DESC(debug, "Debug enabled or not");