GSM access to the internet

Yes, to run your program with modules attached to the mainboard the drivers need to be on board. They will be deployed to the mainboard with your program when you press F5 in Visual Studio. But the firmware is already present in your mainboard.

Most drivers for the modules are simple C# classes that provide a user friendly layer to interact with the module. You could use the music module without the drivers and write the data to the correct pin on the mainboard. But there are some special commands you need to write to the pin before you write the data from the MP3. The music module driver will take care of writing those special commands to the module and initialize it for you.

I have the SM5100B cellular shield from Sparkfun http://www.sparkfun.com/products/9607 that I use with the Panda2 and it’s not very easy to use and requires a lot of programming. I’m actually hoping that the module from Seedstudio will have some code that will help me better use the module. I chose this solution as I work in telecoms and do some specific tests on our local test networks.

If I’d just need wireless 2G/3G internet I’d suggest getting a Wifi shield and either use a pocket 3G over Wifi access point like this one: Amazon.com (there are many others, probably even cheaper, this is just the first thing that popped up on Amazon) or get a cheap mobile phone with Wifi tethering. I tested a Nokia E71 that I got for 10€ with a prepaid card along with a 10€ application for the wifi tethering and it worked just great. Plus you get 3G speed this way while most GSM modules are only 2G.

The other advantage using an external wifi<->GSM bridge is that you can update to newer technology like 4G/LTE without changing anything on your embedded device.

I also need 3G , but I can’t find a good example in code share page or wiki.
Will GHI provide a 3G related example and driver in the web?

It is a good solution for "getting a Wifi shield and either use a pocket 3G over Wifi access point ".
I have considered it before.
But in some engineering applications, like mine. The power consumption is the critical issue. The device is deployed on a hard to reach place. It is hard to replace the battery. The (Wifi+3G) may take high power consumption.
But Maybe ultra low power WIFI will be a solution?
I find this.
http://www.rovingnetworks.com/products/RN_XV
Does anyone used it ? better than Digi’s Xbee wifi?

I have the RNXV and it works great. I do not have the Digi wifi module. The main difference between the two, other than a completely different API, is Digi’s supports 802.11 B/G/N, and the RNXV supports only B/G. The RNXV is considerably less expensive (almost half), I’m guessing because of the lack of N radio circuitry. If you pause to do the math, you could not collect serial data fast enough to need N speeds. My personal opinion is Digi charges more because the XBees have become so popular, so they are capitalizing on their well established brand name.

If you need 3G/UMTS speed than you first need a module that supports this. None of the commonly available GSM shields support 3G, they only work with GSM (Voice/Fax/Data/SMS) and GPRS.

Update: I had proposed an EDGE module thinking it was 3G but actually EDGE is only 2.5G (it’s enhanced gprs). It’s faster than the usual GSM shields but doesn’t provide 3G speed. I have removed this paragraph.

If power is your main concern though I wouldn’t use 3G traffic at all because it needs a lot of power (4G/LTE is even worse). If you don’t have any power sockets at the location where your device is going to operate then using a GSM shield would be the best solution to avoid the power necessary for the Wifi on the Hydra and the MiFi (mobile 3G hotspot). Even then I guess you’d have to look into something as powerful as a car battery unless you want to go switch batteries every few days.

Or when us want to use UMTS lke a surf stick with a sim card (UMTS-Stick) you can use the USB host and try to write a driver for it and a little software. Thats what I want to try :slight_smile:

I borrowed a UMTS surf stick from work and checked it out on my PC. Looks like it is adding two virtual com ports, one called Diagnostics and the other called Application Interface. It also adds a network device and a virtual cdr for the drivers.

I haven’t had much time with that thing yet but I connected to the Application com port and gave it an AT&F and the thing responded with OK. So it seems to follow standard AT interface commands.

Now I’ll have to check if it actually works with one of the serial2usb drivers that come with the GHI SDK. If that works and the module does support the standard GSM at command set, it might actually be usable with a netmf board similar to the other modules. I’ll let you know if I find out anything else.

In some weeks, when I have some hardware, USB Client SP Module, FEZ Spider and USB Host I will look at it what I have to do to get access to the umts stick via this USB host. If you have find smth new let me know it :slight_smile:

Btw, sounds great what you have tested :slight_smile:

Well I tested the thing on my ChipWorkX (my USBHost module for the Hydra is in transit) and it found nothing but the Mass Storage Device. I haven’t found any way to simply tell the thing to start up with cdrom disabled. It seems something is necessary to switch the stick from Mass Storage to Serial Line mode…

So far I found this linux app which seems to be doing the mode switch: http://www.peck.org.uk/ozerocdoff.html but I haven’t checked the code yet.

I think once we managed to put the device in nocdrom mode it will be easy/easier to use. However for full networking support you might need ppp support and I’m not sure this is available for the Hydra. It’s part of the ChipWorkX for sure. Maybe someone can check and confirm either way?

Below is the code of the Zero-CD disabler.

I installed a serial and usb sniffer on my PC and found out that the serial application port is (at least in the way it’s set up on Windows) is only used for “call control” (setting up the connection) while the data is transmitted over the raw usb socket. However it may very well be that there is an alternate mode available that works similar to the other GSM modules like the SM5100B that I have where you can get data via the serial port. I’ll have to try this manually.

I guess the first piece of action is to actually figure out how to port the program below to C#. I haven’t read the whole thing yet but it seems to simply close the mass storage device in order for the other devices to appear. I took a quick look at the USBHost namespace in the GHI library but haven’t seen anything obvious to forcefully remove a device. If anyone has any suggestions please let me know.


/*
  Option Zero-CD Disabler or simple turn off hack

  Copyright (C) 2008  Peter Henn (support@ option.com)

  Note, most of the part coming from  Josua Dietze usb_modeswitch

  We use this way to disable the ZeroCD device, because we have seen some
  problems during the USB-SCSI device "unplug" and "SCSI disconnect", which
  may result into a complete aystem freezes. Although this disabling of the
  Zero-CD device is a simple SCSI rezero command, the WWAN-modem firmware
  does sometimes not correctly do a "SCSI discnnection" to the USB SCSI
  driver, before it just plug off from the SCSI bus and does require a
  USB reenumeration with the WWAN-modem USB interfaces instead of the USB
  SCSI CD-ROM device.
  Unbinding the USB SCSI driver and sending the USB rezero command simple by
  the usage of the libusb directly from user space solve this time critical
  handling between the SCSI driver and the firmware.

  History:
  0.1, 2008/04/10 P.Henn
       - Initial version with usage of code example from usb_modeswitch
  0.2, 2008/04/14 P.Henn
       - several bugfixes
       - autosetup endpoint address
       - ensure support for three firmware classes
  0.3, 2008/04/15 P.Henn
       - first optional filename compare support
  0.4, 2008/06/09 P-Henn
       - add log file functionality
       - add harder Zero-CD device search phase, if /sys/class/usb_device
         is not supported
       - add search try option

  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:

  http://www.gnu.org/licenses/gpl.txt

*/

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <assert.h>
 #include <signal.h>
 #include <ctype.h>

 #include <stdarg.h>
 #include <getopt.h>
 #include <usb.h>
 #include <dirent.h>

 #define VERSION "0.4"
 #define TARGET_VENDOR 0x0af0
 #define BUFFER_SIZE 65535


// some defines lend from the /usr/include/linux/usb/ch9.h
 #define USB_ENDPOINT_XFERTYPE_MASK      0x03    /* in bmAttributes */
 #define USB_ENDPOINT_XFER_BULK          2
 #define USB_ENDPOINT_DIR_MASK           0x80
 #define USB_DIR_OUT                     0       /* to device */
 #define USB_DIR_IN                      0x80    /* to host */

 #define UDEV_POLL_PERIOD                100     /* in ms, must be > UDEV_POLL_PERIOD_MIN, should be > 55ms and <= 100ms */
 #define UDEV_POLL_PERIOD_MIN            10      /* in ms, should be > 5ms and <= 10ms */



static struct option long_options[] =
{
    {"help",	       	no_argument,       NULL, 'h'},
    {"device_id",	required_argument, NULL, 'i'},
    {"usb_filename",	optional_argument, NULL, 'f'},
    {"namelen",         optional_argument, NULL, 'n'},
    {"quiet",		no_argument,       NULL, 'q'},
    {"debug",           no_argument,       NULL, 'd'},
    {"warn_only",       no_argument,       NULL, 'w'},
    {"version",		no_argument,       NULL, 'v'},
    {"test",            no_argument,       NULL, 't'},
    {"log",             required_argument, NULL, 'l'},
    {"searchtime",      required_argument, NULL, 's'},
    {NULL, 0, NULL, 0}
};



int debug = 0;                   /* commandline switch print debug output */
int namelength = 1;              /* commandline switch of prefered name length */
struct usb_dev_handle *usb_hd;   /* global for usage in signal handler */


/* Function Protortype */
void release_usb_device(int);
struct usb_device* search_devices(int, int, const char*);
int search_message_endp(struct usb_device *);
int search_response_endp(struct usb_device *);
void print_usage(void);
const char *strrcut(const char *, int);
int strrcmp(const char *, const char *);
FILE *errlog;
FILE *outlog;


/**
 * print usage
 * prints just the help text to sreen, for all the nice options, which may be used
 */
void print_usage(void) {
        printf ("Usage: ozerocdoff [-hqwqv] -i <DeviceID> [-f <name>] [-n <len>]\n\n");
	printf (" -h, --help               this help\n");
	printf (" -i, --device_id <n>      target USB device id, required option\n");
	printf (" -f, --usb_filename <str> target USB file name\n");
	printf (" -n, --namelen <n>        target USB file name len (default %d)\n", namelength);
	printf (" -w, --warn_only          print warnings instead of errors without program abort\n");
	printf (" -q, --quiet              don't show messages\n");
	printf (" -t, --test               test only, nothing send\n");
	printf (" -l, --log                write message into log file instead of stderr\n");
	printf (" -s, --searchtime <n> ms  tries to search at least <n> ms for the Zero-CD device\n");
	printf (" -d, --debug              output some debug messages\n");
	printf (" -v, --version            show version string\n\n");
	printf ("Examples:\n");
	printf ("   ozerocdoff -i 0xc031\n");
	printf ("   ozerocdoff -i 0xc031 -f usbdev5.28 -n 2\n");
}



int main(int argc, char **argv) {
	struct usb_device *usb_dev;
	int quiet = 0;            /* commandline switch be quiet, no output */
	int warno = 0;            /* commandline switch do only warn and do no program abort */
	int test = 0;             /* commandline switch for testing, no rezero will be send */
	int count;                /* retry counter */
	int ret;                  /* general return value checker */
	int searchtime;           /* search time in ms to the Zero-CD device */
	DIR *usb_dev_dir;         /* just for testing, if directory exists */
	const char *filename="";  /* filename of this USB device */
        const char *logname=(char *)NULL;/* filename of log file */
	char buffer[BUFFER_SIZE];

	int TargetProduct=0;      /* has not to be zero */

	const char const MessageContent[]={
	  0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12,
	  0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x01,
	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};
	
	int c, option_index = 0;
	usb_dev_dir = opendir ("/sys/class/usb_device/");
	if (usb_dev_dir != NULL) {
	      closedir (usb_dev_dir);
	      searchtime = 0;    /* no search time needed */
	} else {
	      searchtime = 800;  /* set search time to 800 ms */
	}

	while (1){
                c = getopt_long (argc, argv, "hvwdtqi:n:f:l:s:",
                        long_options, &option_index);
		if (c == -1) {
		        break;
		}
		switch (c) {
		case 'i': TargetProduct = strtol(optarg, NULL, 0); break;
		case 'n': namelength = strtol(optarg, NULL, 0); break;
		case 'f': filename = optarg; break;
		case 'l': logname = optarg; break;
		case 's': searchtime = strtol(optarg, NULL, 0); break;
	        case 'q': quiet=1; break;
		case 'd': debug=1; break;
	        case 'w': warno=1; break;
	        case 't': test=1; break;
		case 'v': printf("ozerocdoff version: %s\n", VERSION); exit(0);
		case 'h': print_usage(); exit(0);
		default:  print_usage(); exit(1);
		}
	}

	if (  (logname == (char *)NULL)
	    ||((outlog = errlog = fopen(logname, "a")) == NULL)) {
	        outlog = stdout;
	        errlog = stderr;
	} else {
	      fprintf(outlog, "\n");
	      for(count=0; count < argc; count++) {
	              fprintf(outlog, "%s ", argv[count]);
	      }
	      fprintf(outlog, "\n");
	}

	/* check argument */
	if (TargetProduct==0) {
	        fprintf(errlog, "ERROR: Device ID missing\n");
		exit(1);
	}
	if (debug) quiet=0;
	if (searchtime < 0) {
	        searchtime = 0; /* search at least one time */
	}

       	/* general USB-Lib init stuff */
	usb_init();
        /* if the searchtime is < UDEV_POLL_PERIOD_MIN, we will search only once for the device node, but
           we will wait that searchtime just before we do the first test!
           if the searchtime is > UDEV_POLL_PERIOD, we will repeat the test and do a retest after this time
           period. If the rest of the time is < UDEV_POLL_PERIOD_MIN, we will simple skip the last test,
           otherwise we do a last test after the rest wait time */
	if ((searchtime < UDEV_POLL_PERIOD_MIN) && (searchtime > 0)) {
	        usleep(searchtime*1000);
	}
	for (count=searchtime, ret=1; count>=(UDEV_POLL_PERIOD_MIN - UDEV_POLL_PERIOD); count-=UDEV_POLL_PERIOD, ret++) {
	        (void)usb_find_busses();
		(void)usb_find_devices();

		if (debug) {
		        fprintf(outlog, "%d. Search Zero-CD device\n", ret);
		}
		/* we use currently only the given device ID from the command line to detect the device */
		/* that will be bad, if we want to distingush between multiple WWAN-modems, to take care! */
		usb_dev = search_devices(TARGET_VENDOR, TargetProduct, strrcut(filename, namelength));
		if (usb_dev != NULL) {
		        break;
		} else {
		        if ((count >= UDEV_POLL_PERIOD_MIN) && (count < UDEV_POLL_PERIOD)) {
			      usleep(count*1000);
			} else if (count > UDEV_POLL_PERIOD) {
			      usleep(UDEV_POLL_PERIOD*1000);
			}
		}
	}
	if (usb_dev == NULL) {
	        if(!quiet) fprintf(errlog, "ERROR: No Zero-CD device found\n");
		      exit(2);
		}
	usb_hd = usb_open(usb_dev);
	if (usb_hd == NULL) {
		if(!quiet) fprintf(errlog, "ERROR: device access not possible\n");
		exit(4);
	}
    
	/* detach running default driver */
	signal(SIGTERM, release_usb_device);
	ret = usb_get_driver_np(usb_hd, 0, buffer, sizeof(buffer));
	if (ret == 0) {
	        if (debug) {
		        fprintf(outlog, "Found attached driver: %s\n", buffer);
		}
	        ret = usb_detach_kernel_driver_np(usb_hd, 0);
		if (ret != 0) {
		        if(!quiet) fprintf(errlog, "ERROR: unsuccessful kernel driver detaching\n");
			(void)usb_close(usb_hd);
			exit(5);
		}
	} else {
	        /* hopefully no default kernel driver yet running, send only a warning */
	        if(!quiet) fprintf(errlog, "WARNING: No kernel driver attached found\n");
	}
	ret = usb_claim_interface(usb_hd, 0);
	if (ret != 0) {
		if(!quiet) fprintf(errlog, "ERROR: could not claim interface\n");
		(void)usb_close(usb_hd);
		exit(6);
	}
	  

	/* findout the Message and Response Endpoint */	
        int MessageEndpoint=search_message_endp(usb_dev);
	int ResponseEndpoint=search_response_endp(usb_dev);
	if (MessageEndpoint == 0) {
		if(!quiet) fprintf(errlog, "ERROR: could not detremine Endpoint addresses\n");
		(void)usb_close(usb_hd);
		exit(6);
	}
	if (debug) {
	        fprintf(outlog,"MessageEndpoint:  0x%x\n", MessageEndpoint);
		fprintf(outlog,"ResponseEndpoint:  0x%x \n", ResponseEndpoint);
	}


	/* preparation to send rezero string */
       	(void)usb_clear_halt(usb_hd, MessageEndpoint); //ResponseEndpoint
        ret = usb_set_altinterface(usb_hd, 0);
	if (ret != 0) {
	        if (warno) {
		        if(!quiet) fprintf(errlog, "WARNING: unsuccessful set alternative interface\n");
		} else {
		        if(!quiet) fprintf(errlog, "ERROR: unsuccessful set alternative interface\n");
			(void)usb_release_interface(usb_hd, 0);
			(void)usb_close(usb_hd);
		        exit(7);
		}
	}


	/* usb mass storage setting time (needed by some WWAN modems) */
	sleep(1);

	if (!test) {
	        /* send rezero string */
	        ret = usb_bulk_write(usb_hd, MessageEndpoint, (char *)MessageContent, sizeof(MessageContent), 1000);
	        if (ret < 0) {
	                if (warno) {
			        if(!quiet) fprintf(errlog, "WARNING: unsuccessful write rezero string\n");
			} else {
			        if(!quiet) fprintf(errlog, "ERROR: unsuccessful write rezero string\n");
				(void)usb_release_interface(usb_hd, 0);
				(void)usb_close(usb_hd);
				exit(8);
			}
		} else {
		        if (debug) fprintf(outlog, "Have successfully send ZERO-CD disabling command\n");
		}
		/* needed by some WWAN modems) */
		if (ResponseEndpoint != 0) {
		        ret = usb_bulk_read(usb_hd, ResponseEndpoint, buffer, BUFFER_SIZE, 1000);
			if (ret < 0 ) {
			        if(!quiet) fprintf(errlog, "WARNING: unsuccessful read response message\n");
			}
		}
	}


	/* close device */
	ret = usb_close(usb_hd);
	if (ret < 0) {
	        if (warno) {
		        if(!quiet) fprintf(errlog, "WARNING: closeing failed\n");
		} else {
		        if(!quiet) fprintf(errlog, "ERROR: closeing failed\n");
			(void)usb_release_interface(usb_hd, 0);
			exit(9);
		}
	}	


	/* search again to check result. Note that still the search is needed by some WWAN modems! */
	for (count = 5; (count>0) && (usb_dev != NULL); count--) {
       	        sleep(1);
		(void)usb_find_devices();
		usb_dev = search_devices(TARGET_VENDOR, TargetProduct, "");
	}
	if (usb_dev != NULL) {
	        if (warno) {
		        if(!quiet) fprintf(errlog, "WARNING: Zero-CD device still found\n");
		} else {
		        if(!quiet) fprintf(errlog, "ERROR: Zero-CD device still found\n");
			(void)usb_release_interface(usb_hd, 0);
			exit(10);
		}
	} else {
	        if (debug) fprintf(outlog, "Checked successfully ZERO-CD disabled\n");
		else if(!quiet) fprintf(outlog, "Successfully ZERO-CD disabled\n");
	}



	/* relese device */
	(void)usb_release_interface(usb_hd, 0);
	return 0;
}


/**
 * release_usb_device
 * need for the signal handler to ensure proper usb port close and release
 *
 * input param : just a dumy paramter
 * return      : nothting
 */
void release_usb_device(int param) {
	(void)usb_release_interface(usb_hd, 0);
	(void)usb_close(usb_hd);
}


/**
 * strrcut
 * string help function, which cuts the string and returns the 
 * right boundary last 'n' characters from the given string 's' or
 * an empty string, if the given string length is shorter than 'n'
 *
 * input s  : const string
 * input n  : number of charaacters, which should be left on the 
 *            right side of the given string
 * return   : the result (shorten) strinf or empty string
 */
const char *strrcut(const char *s, int n) {
        if (strlen(s)>=n) {
	        return &(s[strlen(s)-n]);
	} else {
	        return "";
	}
}

/**
 * strrcmp
 * string help function, which is used to compare just the right
 * part of the given two strings. All other part is just cut away or
 * not be used for the comparision
 *
 * input s1 : const 1st string
 * input s2 : const 2nd string
 * return   : the strcmp return value of the shorted given strings
 */
int strrcmp(const char *s1, const char *s2) {
      if (strlen(s1)<=strlen(s2)) {
	      return strcmp(s1,strrcut(s2,strlen(s1)));
      } else {
	      return strcmp(strrcut(s1,strlen(s2)),s2);
      }
}


/** search_devices
 * search function of the vendor and device id. Optional the name can 
 * be used to compare the right part of found string of the usblib.
 *
 * input vendor  : USB vendor id
 * input product : USB product id
 * input name    : optional right part of the searched filename or just an empty string
 * return        : the found usb device structure, which matches the search
 */
struct usb_device* search_devices(int vendor, int product, const char * name) {
        struct usb_bus *bus;
    
	for (bus = usb_get_busses(); bus; bus = bus->next) {
		struct usb_device *dev;
		for (dev = bus->devices; dev; dev = dev->next) {
		        if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
			        /* check number of Endpoints, class, subclass and protocol */
			        if (debug) {
				        fprintf(outlog, "Endpoints: %d  (2)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints);
					fprintf(outlog, "Class:     0x%x  (0x08)\n", dev->config[0].interface[0].altsetting[0].bInterfaceClass);
					fprintf(outlog, "SubClass:  0x%x  (0x06)\n", dev->config[0].interface[0].altsetting[0].bInterfaceSubClass);
					fprintf(outlog, "Protocol:  0x%x  (0x50)\n", dev->config[0].interface[0].altsetting[0].bInterfaceProtocol);
				}
				if (   (dev->config[0].interface[0].altsetting[0].bNumEndpoints == 2)
				    && (dev->config[0].interface[0].altsetting[0].bInterfaceClass == 0x08)
				    && (dev->config[0].interface[0].altsetting[0].bInterfaceSubClass == 0x06)
				    && (dev->config[0].interface[0].altsetting[0].bInterfaceProtocol == 0x50) ) {
				        if (debug) {
					        fprintf(outlog, "Found file name: '%s'\n", dev->filename);
						fprintf(outlog, "Required last chars of file name: '%s'\n", name);
					}
					if (strrcmp(name, dev->filename) == 0) {
					        if (debug) fprintf(outlog, "UMS interface found\n");
						return dev;
					} else {
					        if (debug) fprintf(outlog, "UMS interface found, but its wrong\n");
					}
				}
			}
		}
	}
	return NULL;
}

/**
 * search_message_endp
 * looks inside the USB descriptor stuff for the needed endpoint address. 
 * It searches explicit for an bulk output interface and returns the address
 * or even zero
 *
 * input dev : usb device structure
 * return    : endpoint address of 0, if it is no bulk output endpoint
 */
int search_message_endp(struct usb_device *dev) {
        if (  ((dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
	    &&((dev->config[0].interface[0].altsetting[0].endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)) {
	        return dev->config[0].interface[0].altsetting[0].endpoint[0].bEndpointAddress; 
	} else 
	        if (  ((dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
	            &&((dev->config[0].interface[0].altsetting[0].endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)) {
	                return dev->config[0].interface[0].altsetting[0].endpoint[1].bEndpointAddress;
	}
	return 0;
}

/**
 * search_response_endp
 * looks inside the USB descriptor stuff for the needed endpoint address. 
 * It searches explicit for an bulk input interface and returns the address
 * or even zero
 *
 * input dev : usb device structure
 * return    : endpoint address of 0, if it is no bulk input endpoint
 */
int search_response_endp(struct usb_device *dev) {
        if (  ((dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
	    &&((dev->config[0].interface[0].altsetting[0].endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)) {
	        return dev->config[0].interface[0].altsetting[0].endpoint[0].bEndpointAddress; 
	} else 
	        if (  ((dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
	            &&((dev->config[0].interface[0].altsetting[0].endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)) {
	                return dev->config[0].interface[0].altsetting[0].endpoint[1].bEndpointAddress;
	}
	return 0;
}




Updated with new information!

Sorry for the triple post… I got an error from the webserver so I hit resend thinking it wasn’t posted when it actually was…

Either way I made some progress… I implemented the code from the program I posted earlier… here is the output for the code below:

Basically that means that once I manage for the device to disable the cdrom driver, it comes up with a new device with type 0 = unknown. Now I’ll have to figure out what to do with this unknown device and how to get the serial ports enabled…

Update: I checked the devices and endpoints attached to the device… here is the result:


Device connected...
ID: 600796740, Interface: 255, Type: 0, PID: 53333 ,VID: 2800
USB Unknown device detected...
Looking for interfaces and endpoints...
Device: 0 Class: 255 Subclass: 255
     Endpoint: 0 bmAttributes: 2
     Endpoint: 1 bmAttributes: 2
Device: 1 Class: 255 Subclass: 255
     Endpoint: 0 bmAttributes: 2
     Endpoint: 1 bmAttributes: 2
Device: 2 Class: 255 Subclass: 255
     Endpoint: 0 bmAttributes: 3
     Endpoint: 1 bmAttributes: 2
     Endpoint: 2 bmAttributes: 2
Device: 3 Class: 255 Subclass: 255
     Endpoint: 0 bmAttributes: 2
     Endpoint: 1 bmAttributes: 2
Device: 4 Class: 255 Subclass: 255
     Endpoint: 0 bmAttributes: 2
     Endpoint: 1 bmAttributes: 2

Here is the code I used so far: it’s just for testing at the moment so I haven’t bothered setting up a library class for this stuff yet.

Update: Code including identification of the new unknown device!


using System.Threading;
using Microsoft.SPOT;
using GHIElectronics.NETMF.USBHost;

namespace USBHostTest
{
    public class Program
    {
        public static void Main()
        {
            USBHostController.DeviceConnectedEvent += new USBH_DeviceConnectionEventHandler(USBHostController_DeviceConnectedEvent);
            USBHostController.DeviceDisconnectedEvent += new USBH_DeviceConnectionEventHandler(USBHostController_DeviceDisconnectedEvent);

            // Sleep forever
            Thread.Sleep(Timeout.Infinite);
        }

        static void USBHostController_DeviceDisconnectedEvent(USBH_Device device)
        {
            Debug.Print("Device disconnected...");
            Debug.Print("ID: " + device.ID + ", Interface: " +
                        device.INTERFACE_INDEX + ", Type: " + device.TYPE);
        }

        static void USBHostController_DeviceConnectedEvent(USBH_Device device)
        {
            Debug.Print("Device connected...");
            Debug.Print("ID: " + device.ID + ", Interface: " +
                        device.INTERFACE_INDEX + ", Type: " + device.TYPE+", PID: "+device.PRODUCT_ID+" ,VID: "+device.VENDOR_ID);

            if (device.TYPE == USBH_DeviceType.Unknown)
            {
                Debug.Print("USB Unknown device detected...");
                USBH_RawDevice rawdev = new USBH_RawDevice(device);
                rawdev.Disconnected += new USBH_RawDeviceEventHandler(rawdev_Disconnected);
                USBH_Descriptors.Configuration desc = rawdev.GetConfigurationDescriptors(0);
                //USBH_Descriptors.Endpoint rawEP = null;
                Debug.Print("Looking for interfaces and endpoints...");
                for (int i = 0; i < desc.interfaces.Length; i++)
                {
                    Debug.Print("Device: " + i + " Class: " + desc.interfaces[i].bInterfaceClass+" Subclass: "+desc.interfaces[i].bInterfaceSubclass);
                    for (int ep = 0; ep < desc.interfaces[i].endpoints.Length; ep++)
                    {
                        Debug.Print("     Endpoint: " + ep + " bmAttributes: " + desc.interfaces[i].endpoints[ep].bmAttributes);
                    }

                }

            }

            // Remove USB CDROM drive to get the real interface
            if (device.TYPE == USBH_DeviceType.MassStorage)
            {
                Debug.Print("USB Mass Storage detected...");
                USBH_RawDevice rawdev = new USBH_RawDevice(device);
                rawdev.Disconnected += new USBH_RawDeviceEventHandler(rawdev_Disconnected);
                USBH_Descriptors.Configuration desc = rawdev.GetConfigurationDescriptors(0);
                rawdev.SendSetupTransfer(0x0, 0x09, desc.bConfigurationValue, 0x0);
                USBH_Descriptors.Endpoint rawEP = desc.interfaces[0].endpoints[1];
                USBH_RawDevice.Pipe rawpipe = rawdev.OpenPipe(rawEP);
                byte[] disc_msg = new byte[] {
	                0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12,
	                0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x01,
	                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	            };
                rawpipe.TransferData(disc_msg, 0, disc_msg.Length);
            }
        }

        static void rawdev_Disconnected(USBH_RawDevice sender, USBH_RawDeviceEventArgs args)
        {
            Debug.Print("RAW device sucessfuly disconnected.");
        }

    }

}


Update: I saw the example for the silabs serial device which was forced because it wasn’t detected.

So I tried that but it raises an exception… and I think it’s because the serial port needs to be attached not to the device itself but one of the subdevices (does this make sense?).

If you look at the updated output above there are 5 sub-interfaces attached to the one device. I believe two of these interfaces are serial com ports and the rest are modem device, ethernet device and something else I haven’t identified yet.

So my questions would be can I somehow attach the serial port driver to one of these sub-interfaces?

One more thing… I found this website explaining very detailed how to get a UMTS stick to work under Linux… http://www.kuix.de/umts/vodafone/

I also found out that there are two ways to run the module, either via the USB network interface (which I’m not sure would work in netmf) but also over the legacy serial port with ppp.

Right now the only problem is that I can’t get the three serial subinterfaces to get working… I tried all the USB drivers on the device and I also tried replacing INTERFACE_INDEX (which is 255) in the following code with 0 - 4 (the subinterfaces) but that didn’t help either…

USBH_Device serial_port = new USBH_Device(device.ID,device.INTERFACE_INDEX,USBH_DeviceType.Serial_CDC, device.VENDOR_ID,device.PRODUCT_ID, device.PORT_NUMBER);

I always get the same exception that doesn’t really tell me anything.

I might spend another day or two on this but it’s not a priority for me right now so if anyone else can pick up from here or at least spare some tips on how I might get the serial ports to work I’d really appreciate it.

Hi, what about the problem with the UMTS stick, did you get it working?

Regards
Chris