Thanks a lot Ashely, but what would number do we change the endpoint to?
The way that the library selects the serial ports works like this:
1. The total number of endpoints enumerated is controlled by m_endpointsToFetch, this is usually the number of virtual serial ports multiplied by 2. Most USB virtual serial ports have 3 endpoints, but only two of these are BULK endpoints and the other is an INTERRUPT endpoint. We only need the BULK endpoints. Usually there will be 2 virtual serial ports so set the number of endpoints to 4.
2. The endpoints will be taken from the first interfaces that have BULK endpoints (as indicated by the function useEndpoint). You need to choose which interfaces are selected by altering the parseInterface function for your modem. For the K3770 it looks like this:
bool VodafoneK3770Initializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
{
if( m_hasSwitched )
{
if( intf_class == 0xFF )
{
if( (m_currentSerialIntf == 0) || (m_currentSerialIntf == 4) )
{
m_currentSerialIntf++;
return true;
}
m_currentSerialIntf++;
}
}
else
{
if( (intf_nb == 0) && (intf_class == MSD_CLASS) )
{
return true;
}
}
return false;
}
Which means it selects interfaces the first (0) and fifth (4) interfaces that have interface class 0xFF.
This is a little bit esoteric, but you can construct this parseInterface function to explicitly choose an interface. You could also parse all interfaces by always returning true, and then select out the ports later, but it makes more sense just to enumerate those interfaces that correspond to the serial ports.
How do you know which interfaces are the virtual serial ports? Well this is where you need to look at the device on your OS (after flipping it from MSD mode), and work out which ones are the virtual serial ports. Or you could just experiment a bit with the code until you find them.
3. The last thing you need to do is have an appropriate getEp function, looking at the K3770 again:
USBEndpoint* VodafoneK3770Initializer::getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx)
{
return pDev->getEndpoint(serialPortNumber, BULK_ENDPOINT, tx?OUT:IN, 0);
}
It just returns the serial ports in the order they were found, so serialPortNumber 0 will return the first interface selected as true by parseInterface.
You need to make sure that the first serial port returned, is the serial port that allows AT commands. On modems that have dual serial ports, some reserve one exclusively for the PPP connection and do not allow you to send the full command set to both ports, on other modems, both ports behave the same. This is a modem specific thing. For example, look at the K3772Z:
USBEndpoint* VodafoneK3772ZInitializer::getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx)
{
return pDev->getEndpoint((serialPortNumber==1)?0:1, BULK_ENDPOINT, tx?OUT:IN, 0);
}
In this case, the second serial port (as enumerated) was the one that AT commands had to be sent down, and the first serial port is the one used for PPP. So in this case we just swap around the return order. On other modems (I'm just speculating here) with more serial ports, you might need to return the 3rd serial port and you'd have to change the code accordingly. If you look at most of the examples, most of the time you just need to copy the K3770 example.
BTW, I didn't write this code structure, so I've reversed engineered all this information for you. I did add the K3773 modem by using this information however.
I wanted to write a program that would automatically test each interface and find out automatically what the settings could be, but didn't have time. I also wanted to write a tutorial on how to get the relevant information from Linux or FreeBSD USB interrogation tools, and got somewhere but didn't have time to complete it.
The problem is, many of these vendors use the interface class 0xFF which means "vendor specific" instead of using CDC or ACM mode so there isn't a sure-fire way of determining which are the virtual serial ports other than testing them. Or if they enumerate successfully on the OS you are using, you can try and work out to which interfaces /dev/ttyU0 or whatever corresponds and do it like that.
If I find the time, I'll try and put everything above into a more coherent tutorial. Otherwise you can always contact me privately for consulting services from my company.
Ashley
Hello!
I've tried a few times to get my K3772 (there's no "z" at the end in any of the docs, and I'm wondering if that might be the problem?) to work - without success.
I'll confess to being something of a newb to this, and would really appreciate any tips for debugging.
First - how the blazes do you turn the [DBG] messages on?
Second - Is there a super verbose test harness / version of the library?