berry_charge.c 3.6 KB

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