Re: [usb-storage] Toshiba G450 kernel patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Matt,

> What's the deal with the "special" inquiry command you send as part of
> initialization?  The code suggests that you're trying to detect something,
> but all you look for is a response to, as far as I can tell, a normal
> INQUIRY command....

I just played with the patch again to fine tune patch file to comply
requirements of checkpatch.pl script and I also tested if I really
can somehow drop that fake inquiry. I've found out that it is not
possible. That device does not respond correctly during first bulk
transfer and this inquiry detects it and as the init routine exits
with 0 error code even after wrong result of inquiry routine,
usb-store module does not send error message into syslog.
Second and subsequent transfers work so second inquiry returns
with 0 code and the switchmode routine is run afterwards.
And switch mode should run well otherwise init will return with -EIO
error code.

I have cleaned up a bit the patch file. Find it attached to this email.
I've already updated it on the page:
http://www.magdina.org/projects/toshiba-g450-kernel-patch

Peter
Signed-off-by: Peter Magdina <peter@xxxxxxxxxx>

diff -Nparu linux-2.6.31.1-old/drivers/usb/serial/option.c linux-2.6.31.1-new/drivers/usb/serial/option.c
--- linux-2.6.31.1-old/drivers/usb/serial/option.c	2009-10-03 00:14:54.000000000 +0200
+++ linux-2.6.31.1-new/drivers/usb/serial/option.c	2009-10-06 23:16:50.000000000 +0200
@@ -317,6 +317,7 @@ static int  option_resume(struct usb_ser
 /* TOSHIBA PRODUCTS */
 #define TOSHIBA_VENDOR_ID			0x0930
 #define TOSHIBA_PRODUCT_HSDPA_MINICARD		0x1302
+#define TOSHIBA_PRODUCT_G450			0x0d45
 
 #define ALINK_VENDOR_ID				0x1e0e
 #define ALINK_PRODUCT_3GU			0x9200
@@ -578,6 +579,7 @@ static struct usb_device_id option_ids[]
 	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
 	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
 	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
+	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
 	{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
diff -Nparu linux-2.6.31.1-old/drivers/usb/storage/Makefile linux-2.6.31.1-new/drivers/usb/storage/Makefile
--- linux-2.6.31.1-old/drivers/usb/storage/Makefile	2009-10-03 00:14:54.000000000 +0200
+++ linux-2.6.31.1-new/drivers/usb/storage/Makefile	2009-10-03 00:15:40.000000000 +0200
@@ -12,7 +12,8 @@ obj-$(CONFIG_USB_STORAGE)	+= usb-storage
 usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
 
 usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
-			initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
+			initializers.o sierra_ms.o option_ms.o \
+		       	toshiba_g450.o $(usb-storage-obj-y)
 
 ifeq ($(CONFIG_USB_LIBUSUAL),)
 	usb-storage-objs	+= usual-tables.o
diff -Nparu linux-2.6.31.1-old/drivers/usb/storage/toshiba_g450.c linux-2.6.31.1-new/drivers/usb/storage/toshiba_g450.c
--- linux-2.6.31.1-old/drivers/usb/storage/toshiba_g450.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.31.1-new/drivers/usb/storage/toshiba_g450.c	2009-10-06 23:37:58.000000000 +0200
@@ -0,0 +1,158 @@
+/*
+ * Driver for Toshiba G450 HSDPA modem.
+ *
+ *   (c) 2009 Peter Magdina <peter@xxxxxxxxxx>
+ *
+ * Inspired by option_ms.c by Dan Williams <dcbw@xxxxxxxxxx>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/usb.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "toshiba_g450.h"
+#include "debug.h"
+
+#define G450_FORCE_MODEM		0x01
+#define G450_ALLOW_MS 			0x02
+
+static unsigned int toshiba_g450_cd = G450_FORCE_MODEM;
+module_param(toshiba_g450_cd, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(toshiba_g450_cd, "cd mode (1=Force Modem (default),"
+			" 2=Allow CD-Rom");
+
+#define RESPONSE_LEN 1024
+
+static int toshiba_g450_switchmode(struct us_data *us)
+{
+	const unsigned char switch_msg[] = {
+		0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b,
+		0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	char *buffer;
+	int result;
+
+	US_DEBUGP("Toshiba G450 : DEVICE MODE SWITCH\n");
+
+	buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL);
+	if (buffer == NULL)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	memcpy(buffer, switch_msg, sizeof(switch_msg));
+	result = usb_stor_bulk_transfer_buf(us,
+			us->send_bulk_pipe,
+			buffer, sizeof(switch_msg), NULL);
+	if (result != USB_STOR_XFER_GOOD) {
+		result = USB_STOR_XFER_ERROR;
+		goto out;
+	}
+
+	/* Some of the devices need to be asked for a response, but we don't
+	 * care what that response is.
+	 */
+	usb_stor_bulk_transfer_buf(us,
+			us->recv_bulk_pipe,
+			buffer, RESPONSE_LEN, NULL);
+
+	result = USB_STOR_XFER_GOOD;
+
+	usb_stor_clear_halt(us, us->send_bulk_pipe);
+
+out:
+	kfree(buffer);
+	return result;
+}
+
+static int toshiba_g450_inquiry(struct us_data *us)
+{
+	const unsigned char inquiry_msg[] = {
+		0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
+		0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12,
+		0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	char *buffer;
+	int result;
+
+	US_DEBUGP("Toshiba G450 : device inquiry\n");
+
+	buffer = kzalloc(0x24, GFP_KERNEL);
+	if (buffer == NULL)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	memcpy(buffer, inquiry_msg, sizeof(inquiry_msg));
+	result = usb_stor_bulk_transfer_buf(us,
+			us->send_bulk_pipe,
+			buffer, sizeof(inquiry_msg), NULL);
+	if (result != USB_STOR_XFER_GOOD) {
+		result = USB_STOR_XFER_ERROR;
+		goto out;
+	}
+
+	result = usb_stor_bulk_transfer_buf(us,
+			us->recv_bulk_pipe,
+			buffer, 0x24, NULL);
+	if (result != USB_STOR_XFER_GOOD) {
+		result = USB_STOR_XFER_ERROR;
+		goto out;
+	}
+
+	/* Read the CSW */
+	usb_stor_bulk_transfer_buf(us,
+			us->recv_bulk_pipe,
+			buffer, 13, NULL);
+
+	usb_stor_clear_halt(us, us->send_bulk_pipe);
+
+out:
+	kfree(buffer);
+	return result;
+}
+
+
+int toshiba_g450_init(struct us_data *us)
+{
+	int result;
+
+	US_DEBUGP("Toshiba G450 : toshiba_g450_init called\n");
+
+	result = toshiba_g450_inquiry(us);
+	if (result != 0) {
+		US_DEBUGP("Toshiba G450 : unable to inquire device,"
+				  " no action taken\n");
+		return 0;
+	}
+
+	/* Force Modem mode */
+	if (toshiba_g450_cd == G450_FORCE_MODEM) {
+		US_DEBUGP("Toshiba G450 : Forcing Modem Mode\n");
+		result = toshiba_g450_switchmode(us);
+		if (result != USB_STOR_XFER_GOOD) {
+			US_DEBUGP("Toshiba G450 : Failed to switch"
+					  " to modem mode.\n");
+			return -EIO;
+		}
+	} else if (toshiba_g450_cd == G450_ALLOW_MS) {
+		/* Allow Mass Storage mode (keep CD-Rom) */
+		US_DEBUGP("Toshiba G450 : Allowing Mass Storage Mode"
+				  " if device requests it\n");
+	}
+
+	return 0;
+}
diff -Nparu linux-2.6.31.1-old/drivers/usb/storage/toshiba_g450.h linux-2.6.31.1-new/drivers/usb/storage/toshiba_g450.h
--- linux-2.6.31.1-old/drivers/usb/storage/toshiba_g450.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.31.1-new/drivers/usb/storage/toshiba_g450.h	2009-10-03 00:15:40.000000000 +0200
@@ -0,0 +1,4 @@
+#ifndef _TOSHIBA_G450_H_
+#define _TOSHIBA_G450_H_
+extern int toshiba_g450_init(struct us_data *us);
+#endif
diff -Nparu linux-2.6.31.1-old/drivers/usb/storage/unusual_devs.h linux-2.6.31.1-new/drivers/usb/storage/unusual_devs.h
--- linux-2.6.31.1-old/drivers/usb/storage/unusual_devs.h	2009-10-03 00:14:54.000000000 +0200
+++ linux-2.6.31.1-new/drivers/usb/storage/unusual_devs.h	2009-10-06 23:38:17.000000000 +0200
@@ -1110,6 +1110,13 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xf
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
+/* Patch by Peter Magdina <peter@xxxxxxxxxx> */
+UNUSUAL_DEV(0x0930, 0x0d46, 0x0000, 0x0000,
+		"Toshiba G450",
+		"Mass Storage",
+		US_SC_DEVICE, US_PR_DEVICE, toshiba_g450_init,
+		0),
+
 /* This Pentax still camera is not conformant
  * to the USB storage specification: -
  * - It does not like the INQUIRY command. So we must handle this command
diff -Nparu linux-2.6.31.1-old/drivers/usb/storage/usb.c linux-2.6.31.1-new/drivers/usb/storage/usb.c
--- linux-2.6.31.1-old/drivers/usb/storage/usb.c	2009-10-03 00:14:54.000000000 +0200
+++ linux-2.6.31.1-new/drivers/usb/storage/usb.c	2009-10-03 00:15:42.000000000 +0200
@@ -68,6 +68,7 @@
 
 #include "sierra_ms.h"
 #include "option_ms.h"
+#include "toshiba_g450.h"
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@xxxxxxxxxxxxxxxxxx>");

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux