-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
Unknow Device(vid=1edf,pid=6003)
Today, I get a 3G modem from Russia unsupported by our system. when I plug it into the PC with OS is Linux(2.6.30), cat the file /proc/bus/usb/devices, it shows:
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 2
P: Vendor=1edf ProdID=6003 Rev= 0.00
S: Manufacturer=Selectwireless Incorporated
S: Product=Selectwireless CDMA USB Modem
S: SerialNumber=Data Interface
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I: If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none)
E: Ad=87(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=08(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
C: #Ifs= 4 Cfg#= 2 Atr=80 MxPwr=250mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=84(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=86(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I find that the USB is full mode USB device, and it has two configures, the seconds configure has 4 interfaces, some are vendor interfaces, I think that the device is not need to be switched by mode_switch tool. But when I traverse all the devices and configures, I can not find the vender interface. when I use insmod command to insmod the usbserial.ko, just the configure 1 driver is insmoded, the configure 2 is not.
any advices is appreciated.
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 2
P: Vendor=1edf ProdID=6003 Rev= 0.00
S: Manufacturer=Selectwireless Incorporated
S: Product=Selectwireless CDMA USB Modem
S: SerialNumber=Data Interface
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I: If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none)
E: Ad=87(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=08(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
C: #Ifs= 4 Cfg#= 2 Atr=80 MxPwr=250mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=84(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=86(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I find that the USB is full mode USB device, and it has two configures, the seconds configure has 4 interfaces, some are vendor interfaces, I think that the device is not need to be switched by mode_switch tool. But when I traverse all the devices and configures, I can not find the vender interface. when I use insmod command to insmod the usbserial.ko, just the configure 1 driver is insmoded, the configure 2 is not.
any advices is appreciated.
You can use usb_modeswitch to select the configuration, too.
This would be the config file:You know how to add the udev rule, right ?
BTW, this is the same USB ID and the same setup as the AirPlus MCD-800. It will be in the next data package release.
Edit: fixed erroneous value from "3" to "2".
This would be the config file:
Code: Select all
DefaultVendor= 0x1edf
DefaultProduct=0x6003
TargetClass=0x02
CheckSuccess=10
DetachStorageOnly=1
Configuration=2
BTW, this is the same USB ID and the same setup as the AirPlus MCD-800. It will be in the next data package release.
Edit: fixed erroneous value from "3" to "2".
Last edited by Josh on 04 Nov 2010, 10:14, edited 1 time in total.
-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
"You know how to add the udev rule, right ?"Josh wrote:You can use usb_modeswitch to select the configuration, too.
This would be the config file:You know how to add the udev rule, right ?Code: Select all
DefaultVendor= 0x1edf DefaultProduct=0x6003 TargetClass=0x02 CheckSuccess=10 DetachStorageOnly=1 Configuration=3
BTW, this is the same USB ID and the same setup as the AirPlus MCD-800. It will be in the next data package release.
you mean add a rule in the file usb_modeswitch.conf which the usb_modeswitch parse it to get the device configure? I will try it, thanks a lot!
Ah, no, I meant a line in the file "/lib/udev/rules.d/40-usb_modeswitch.rules" for the automatic switching if you are using it.
And sorry, there is a copy-and-paste error in the config I posted! It should be
And sorry, there is a copy-and-paste error in the config I posted! It should be
Code: Select all
...
Configuration=2
...-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
Josh wrote:Ah, no, I meant a line in the file "/lib/udev/rules.d/40-usb_modeswitch.rules" for the automatic switching if you are using it.
And sorry, there is a copy-and-paste error in the config I posted! It should beCode: Select all
... Configuration=2 ...
OK, I try this method. In my system ,there is no file /lib/udev/rules.d/40-usb_modeswitch.rules, so I call the function mode_usbswitch directly to get the USB informations. here is the logs:
card_add 183 call usb_modeswitch -v 1edf -p 6003 -C 2 -s 10 -d 1 -u 2 &.
Looking for target devices ...
No devices in target mode or class found
Looking for default devices ...
Found devices in default mode or class (1)
Accessing device 002 on bus 001 ...
Using endpoints 0x08 (out) and 0x87 (in)
Using endpoints 0x08 (out) and 0x87 (in)
Inquiring device details; driver will be detached ...
Looking for active driver ...
No driver found. Either detached before or never attached
Start get card info
cat/proc/bus/usb/devices
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 1
B: Alloc= 0/800 us ( 0%), #Int= 0, #Iso= 0
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0000 ProdID=0000 Rev= 2.06
S: Manufacturer=Linux 2.6.15--LSDK-7.3.1.41 ehci_hcd
S: Product=ATH EHCI
S: SerialNumber=ar7240-ehci.0
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 2 Ivl=256ms
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 2
P: Vendor=1edf ProdID=6003 Rev= 0.00
S: Manufacturer=Selectwireless Incorporated
S: Product=Selectwireless CDMA USB Modem
S: SerialNumber=Data Interface
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I: If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usbfs
E: Ad=87(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=08(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
C: #Ifs= 4 Cfg#= 2 Atr=80 MxPwr=250mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=84(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=86(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
Is the command in red color right?
which driver is the device should be attached? ACM driver or usbserial driver. should the driver be insmoded before the usb_modeswitch is called?
-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
I try it again. unfortunately, it is not successful. here is the log:Josh wrote:The command line looks good.
Can you do a manual call (not from a script) with the parameter -W added?
Also, the "cdc_acm" driver should load automatically if you have run "depmod" correctly. You can also load it manually if that doesn't work. You should end up with ttyACM devices.
card_add 183 call usb_modeswitch -v 1edf -p 6003 -C 2 -W -s 10 -d 1 -u 2 &.
Taking all parameters from the command line
* usb_modeswitch: handle USB devices with multiple modes
* Version 1.1.4 (C) Josua Dietze 2010
* Based on libusb0 (0.1.12 and above)
! PLEASE REPORT NEW CONFIGURATIONS !
DefaultVendor= 0x1edf
DefaultProduct= 0x6003
TargetVendor= not set
TargetProduct= not set
TargetClass= 0x02
TargetProductList=""
DetachStorageOnly=1
HuaweiMode=0
SierraMode=0
SonyMode=0
GCTMode=0
MessageEndpoint= not set
MessageContent=""
NeedResponse=0
ResponseEndpoint= not set
Interface=0x00
Configuration=0x02
InquireDevice enabled (default)
Success check enabled, max. wait time 10 seconds
System integration mode disabled
Looking for target devices ...
searching devices, found USB ID 1edf:6003
found matching vendor ID
found matching product ID
target class 02 not matching
searching devices, found USB ID 0000:0000
No devices in target mode or class found
Looking for default devices ...
searching devices, found USB ID 1edf:6003
found matching vendor ID
found matching product ID
target class 02 not matching
adding device as default
searching devices, found USB ID 0000:0000
Found devices in default mode or class (1)
Accessing device 003 on bus 001 ...
Using endpoints 0x08 (out) and 0x87 (in)
Using endpoints 0x08 (out) and 0x87 (in)
Inquiring device details; driver will be detached ...
Looking for active driver ...
No driver found. Either detached before or never attached
usbcore: registered new driver cdc_acm
drivers/usb/class/cdc-acm.c: v0.23:USB Abstract Control Model driver for USB modems and ISDN adapters
Start get card info
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 1
B: Alloc= 0/800 us ( 0%), #Int= 0, #Iso= 0
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0000 ProdID=0000 Rev= 2.06
S: Manufacturer=Linux 2.6.15--LSDK-7.3.1.41 ehci_hcd
S: Product=ATH EHCI
S: SerialNumber=ar7240-ehci.0
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 2 Ivl=256ms
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 2
P: Vendor=1edf ProdID=6003 Rev= 0.00
S: Manufacturer=Selectwireless Incorporated
S: Product=Selectwireless CDMA USB Modem
S: SerialNumber=Data Interface
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I: If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usbfs
E: Ad=87(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=08(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
C: #Ifs= 4 Cfg#= 2 Atr=80 MxPwr=250mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=84(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=
E: Ad=86(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
the command try to find the configure whose class is 2, but it seems that the configure with class 2 is exist and the usb_modeswitch can not find it out. please give me a hand, thank you !
-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
I have read the code of usb_modeswitch(1.1.4), I find in thr function search_devices may has some problem, the code is:Josh wrote:The command line looks good.
Can you do a manual call (not from a script) with the parameter -W added?
Also, the "cdc_acm" driver should load automatically if you have run "depmod" correctly. You can also load it manually if that doesn't work. You should end up with ttyACM devices.
struct usb_device* search_devices( int *numFound, int vendor, int product, char* productList, int targetClass, int mode)
{
struct usb_bus *bus;
char *listcopy, *token, buffer[2];
int devClass;
struct usb_device* right_dev = NULL;
/* only target class given, target vendor and product assumed unchanged */
if ( targetClass && !(vendor || product) ) {
vendor = DefaultVendor;
product = DefaultProduct;
}
*numFound = 0;
/* Sanity check */
if (!vendor || (!product && productList == '\0') )
return NULL;
if (productList != '\0')
listcopy = malloc(strlen(productList)+1);
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next) {
if (verbose)
printf (" searching devices, found USB ID %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct);
if (dev->descriptor.idVendor != vendor)
continue;
if (verbose)
printf (" found matching vendor ID\n");
// product list given
if ( strlen(productList) ) {
strcpy(listcopy, productList);
token = strtok(listcopy, ",");
while (token != NULL) {
if (strlen(token) != 4) {
SHOW_PROGRESS("Error: entry in product ID list has wrong length: %s. Ignoring\n", token);
goto NextToken;
}
if ( hexstr2bin(token, buffer, strlen(token)/2) == -1) {
SHOW_PROGRESS("Error: entry in product ID list is not a hex string: %s. Ignoring\n", token);
goto NextToken;
}
product = 0;
product += (unsigned char)buffer[0];
product <<= 8;
product += (unsigned char)buffer[1];
if (product == dev->descriptor.idProduct) {
if (verbose)
printf (" found matching product ID from list\n");
(*numFound)++;
if (busnum == -1)
right_dev = dev;
else
if (dev->devnum >= devnum && (int)strtol(dev->bus->dirname,NULL,10) == busnum) {
right_dev = dev;
TargetProduct = dev->descriptor.idProduct;
break;
}
}
NextToken:
token = strtok(NULL, ",");
}
/* Product ID is given */
} else
if (product == dev->descriptor.idProduct) {
printf("%s %d dev->descriptor.idProduct = %d\r\n",__FUNCTION__,__LINE__,dev->descriptor.idProduct);
if (verbose)
printf (" found matching product ID\n");
if (targetClass == 0) {
(*numFound)++;
right_dev = dev;
if (verbose)
printf (" adding device\n");
} else {
devClass = dev->descriptor.bDeviceClass;
if (devClass == 0)
devClass = dev->config[0].interface[0].altsetting[0].bInterfaceClass;
else
/* Check for some quirky devices */
printf("%s %d devClass = %d,dev->config[0].interface[0].altsetting[0].bInterfaceClass=%d\r\n",__FUNCTION__,__LINE__,devClass,dev->config[0].interface[0].altsetting[0].bInterfaceClass);
if (devClass != dev->config[0].interface[0].altsetting[0].bInterfaceClass)
devClass = dev->config[0].interface[0].altsetting[0].bInterfaceClass;
printf("%s %d devClass = %d,targetClass=%d\r\n",__FUNCTION__,__LINE__,devClass,targetClass);
if (devClass == targetClass) {
if (verbose)
printf (" target class %02x matching\n", targetClass);
if (mode == SEARCH_TARGET) {
(*numFound)++;
right_dev = dev;
if (verbose)
printf (" adding device\n");
} else
if (verbose)
printf (" not adding device as default\n");
} else {
if (verbose)
printf (" target class %02x not matching\n", targetClass);
if (mode == SEARCH_DEFAULT) {
(*numFound)++;
right_dev = dev;
if (verbose)
printf (" adding device as default\n");
}
}
}
/* hack: if busnum has other than init value, we are called from
* successCheck() and do probe for plausible new devnum/busnum
*/
if (busnum != -1)
if (dev->devnum < devnum || (int)strtol(dev->bus->dirname,NULL,10) != busnum) {
if (verbose)
printf (" busnum/devnum indicates an unrelated device\n");
right_dev = NULL;
}
}
}
}
if (productList != NULL)
free(listcopy);
return right_dev;
}
I am sorry to paste the code. I read the function, I think it just want to find the right device whose vid,pid and class are given, here use to for cycles ,the first for cycle is to search the buses, and the second is to search the devices, but I do not know why it just ust the config[0] to judge if the device is the right one to be searched, actually, there maybe many configs in one device, so , is it should be search all configs in one device and then decide that is it the right one to be search?
I will change the code and test my doubts and tell you the result, have a good weekend.
What you found is likely a problem with finding the target class after switching configurations. I will try to fix that in the next release.
Thanks a lot!
But your problem is unrelated, I think. usb_modeswitch obviously seems to hang or exit after the "no driver found" line. This is the real problem. You never get to the point where the configuration is set (which is happening after all other steps of the process).
Thanks a lot!
But your problem is unrelated, I think. usb_modeswitch obviously seems to hang or exit after the "no driver found" line. This is the real problem. You never get to the point where the configuration is set (which is happening after all other steps of the process).
-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
I think the reason that usb_modeswitch return "no driver found" is that it can not find the right device,just only find it as a default device . what is the default device?a storage device or a usbserial device or a acm device, I do not know. and then it could not find a driver for this default device.Josh wrote:What you found is likely a problem with finding the target class after switching configurations. I will try to fix that in the next release.
Thanks a lot!
But your problem is unrelated, I think. usb_modeswitch obviously seems to hang or exit after the "no driver found" line. This is the real problem. You never get to the point where the configuration is set (which is happening after all other steps of the process).
what is the design method of the usb_modeswith? or could you tell me or send me the document of the greate idea, thanks!
My eamil: zhouqiqiu1982@yahoo.com.cn
-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
I think the reason that usb_modeswitch return "no driver found" is that it can not find the right device,just only find it as a default device . what is the default device?a storage device or a usbserial device or a acm device, I do not know. and then it could not find a driver for this default device.Josh wrote:What you found is likely a problem with finding the target class after switching configurations. I will try to fix that in the next release.
Thanks a lot!
But your problem is unrelated, I think. usb_modeswitch obviously seems to hang or exit after the "no driver found" line. This is the real problem. You never get to the point where the configuration is set (which is happening after all other steps of the process).
what is the design method of the usb_modeswith? or could you tell me or send me the document of the greate idea, thanks!
My eamil: zhouqiqiu1982@yahoo.com.cn
Usually, the first configuration is used, which is of course the storage device (class 08). The "usbstorage" driver should bind to it immediately. I don't know why your's does not. I assume you are on a special embedded system.
The people with the AirPlus MCD-800 reported success with the configuration switch.
See the end of this thread:
http://www.draisberghof.de/usb_modeswit ... =3512#3512
The people with the AirPlus MCD-800 reported success with the configuration switch.
See the end of this thread:
http://www.draisberghof.de/usb_modeswit ... =3512#3512
-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
yes, I try to make it work on a router whose os is Linux. Is it different between the PC and the embedded system?Josh wrote:Usually, the first configuration is used, which is of course the storage device (class 08). The "usbstorage" driver should bind to it immediately. I don't know why your's does not. I assume you are on a special embedded system.
The people with the AirPlus MCD-800 reported success with the configuration switch.
See the end of this thread:
http://www.draisberghof.de/usb_modeswit ... =3512#3512
-
zhouqiqiu1982
- Posts: 27
- Joined: 10 Aug 2010, 16:15
I am very glad to tell you that the problem is resolved. device ttyACM0 is used after the usb_modeswitch. The reason is that in my software there is a function to read the USB device info to judge if mode switch is ok or not, and in the function, it just reads the config[0] while the device has more than one config.Josh wrote:Well, the automatic binding of "usb-storage" does obviously not work on your system, embedded or not. With a standard kernel, the device class 8 is discovered and the driver is loaded. You might check if you have the driver (module or built-in) with just calling "modprobe -v usb-storage".
usb_modeswitch is a very great tool and I thank Josh very much.