[patch] berry_charge.c updated with Blackberry Pearl support, and other bugfixes

Chris Frey <cdfrey-4/[email protected]>
Newsgroups gmane.comp.handhelds.blackberry.barry.devel,gmane.linux.usb.devel
Message-ID <[email protected]>
Hi,

Below is a patch with the following changes to the berry_charge.c module:

1) kzalloc() is called, but memory is never freed

	Is this a memory leak?  I'm not sure, but the buffer is only
	a dummy buffer to hold return data that is never used,
	so I suspect a stack variable will suffice.


2) Added pearl mode change

	Blackberry Pearls start out with a Product ID of 0006, and in
	this mode, only a usb mass storage configuration is available.
	This patch sends the required command to change it from 0006
	to 0004, in which both mass storage and the Blackberry
	database configuration are available.

	Also, Pearls need to be reset explicitly before the power change
	takes effect.


3) Added a sleep() for slow devices.

	My kernel-fu is not up to speed, so I'm sure this is the wrong
	fix, and I hope someone recommends the proper one.  Older devices,
	such as the 7750, are slow to reset, and this creates the
	possibility of the kernel going into an endless loop, detecting
	the device and trying to set the power.  The devices, in some
	cases of my testing, never actually changed to 500mA, but
	the kernel was extremely busy trying to do so, and the entire
	USB subsystem seemed to lock up (lsusb would freeze, for example).

	On my system, the sleep gives the device a chance to change to
	500mA, which prevents the endless loop.


- Chris




--- linux-2.6.21.1/drivers/usb/misc/berry_charge.c	2007-04-27 17:49:26.000000000 -0400
+++ ../linux-2.6.21.1/drivers/usb/misc/berry_charge.c	2007-05-17 14:56:07.000000000 -0400
@@ -26,6 +26,8 @@
 
 #define RIM_VENDOR		0x0fca
 #define BLACKBERRY		0x0001
+#define PEARL_DUAL		0x0004
+#define PEARL			0x0006
 
 static int debug;
 
@@ -36,15 +38,22 @@
 	if (debug)						\
 		dev_printk(KERN_DEBUG , dev , format , ## arg)
 
+/* We watch for product IDs 0001 and 0006, with the idea that
+ * for non-Pearl devices, we only change the charging setting,
+ * and for Pearl devices, we change the charge and the mode.
+ * If a Pearl shows up as 0004, we've already seen it and
+ * don't need to mess with it again.
+ */
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+	{ USB_DEVICE(RIM_VENDOR, PEARL) },
 	{ },					/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
 static int magic_charge(struct usb_device *udev)
 {
-	char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+	char dummy_buffer[2];
 	int retval;
 
 	if (!dummy_buffer)
@@ -78,11 +87,22 @@
 		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 magic_pearl(struct usb_device *udev)
+{
+	char dummy_buffer[2];
+	int retval;
+
+	dbg(&udev->dev, "Sending magic Pearl command\n");
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100);
+	if (retval != 0) {
+		dev_err(&udev->dev, "Pearl magic command failed: %d.\n",
+			retval);
+		return retval;
+	}
 	return retval;
 }
 
@@ -90,6 +110,9 @@
 		       const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
+	int retval;
+
+dbg(&udev->dev, "Dev module, version: 2\n");
 
 	dbg(&udev->dev, "Power is set to %dmA\n",
 	    udev->actconfig->desc.bMaxPower * 2);
@@ -105,6 +128,28 @@
 	/* turn the power on */
 	magic_charge(udev);
 
+	/* change modes if device is a Pearl */
+	if (udev->descriptor.idProduct == PEARL)
+		magic_pearl(udev);
+
+	/* set configuration and reset to activate change */
+	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;
+	}
+
+	/* reset is required by the Pearl */
+	retval = usb_reset_configuration(udev);
+	if (retval) {
+		dev_err(&udev->dev, "Configuration reset failed: %d.\n", retval);
+		return retval;
+	}
+
+	/* give slower devices a chance to reset properly */
+	ssleep(1);
+
 	/* we don't really want to bind to the device, userspace programs can
 	 * handle the syncing just fine, so get outta here. */
 	return -ENODEV;



-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.