Problem: The huawei_cdc_ncm driver (for the 4G LTE dongle Huawei
E3276) gets unregistered and the control device /dev/cdc-wdmN
disappears after sending exactly 121 AT commands to the device. After
a few seconds, the driver is re-registered and the control device
reappears. Test program causing the error included at the end of this
message.
Keywords: huawei_cdc_ncm, LTE, AT commands, cdc-wdm
Detailed problem description:
The behavior has been verified on kernel 3.16.0 and on kernel 3.17.1,
on a 64-bit Core i5 x86 machine and on a a smaller embedded 32-bit x86
machine. Exact command does not matter, used 'ATI' and 'AT^HCSQ?'
with same result. Distros used are Kubuntu 14.04.1 LTS on the i5 and
Debian Wheezy on the embedded machine.
Kernel modules: huawei_cdc_ncm, cdc_ncm
The test program contains some rudimentary C++ but should be readable
even to die-hard C guys ;) The program is crude but hopefully useful
for debugging.
If more info is needed, let me know and I will provide it.
Best regards,
/Erik Alapää
//
// Program that causes temporary loss of cdc-wdmN device and huawei_cdc_ncm
// driver reload after 121 AT commands sent.
//
// No makefile, just compile with 'g++ -g wdm_err.cpp -o wdm_err'.
//
// Usage, see 'Usage: ' message in the code below.
//
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdexcept>
#include <string>
#include <iostream>
#include <fstream>
using std::string;
using std::cout;
using std::runtime_error;
using std::endl;
using std::fstream;
int main(int argc, char* argv[])
{
fd_set rfds;
fd_set wfds;
struct timeval tv;
struct timeval tv2;
int retval;
int n;
const int SZ = 512;
char errbuf[SZ];
char ctrlin_buf[SZ];
//string command("AT^HCSQ?\n");
string command("ATI\n");
string response;
string resp_line;
fstream at_file;
int sleep_us = 0;
int sendcount = 0;
char CTRL_DEVICE[SZ];
// Get file descriptor for select()
if (argc == 3)
{
cout << "Setting AT ctrl device to \'" << argv[1] << "\'\n";
strcpy(CTRL_DEVICE, argv[1]);
cout << "Sleep interval " << sleep_us << " us\n";
}
else
{
cout << "Usage: rw2 <at-ctrl-device> <sleeptime in us> (ctrl
is typically /dev/cdc-wdmN)\n\n";
throw std::runtime_error("Too few args, no ctrl device specified!");
}
int ctrl = open(CTRL_DEVICE, O_RDWR);
if (ctrl == -1)
{
throw std::runtime_error(strerror_r(errno, errbuf, SZ));
}
sleep_us = atoi(argv[2]);
// Get fstream for C++-style reading and writing
at_file.open(CTRL_DEVICE, std::fstream::in | std::fstream::out |
std::fstream::app);
if (!at_file)
{
throw runtime_error("Could not open wdm device file!\n");
}
for (;;)
{
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl, &rfds);
FD_ZERO(&wfds);
FD_SET(ctrl, &wfds);
if (at_file.bad())
{
throw runtime_error("wdm device file gone bad!");
}
tv2.tv_sec = 0;
tv2.tv_usec = sleep_us;
retval = select(0, NULL, NULL, NULL, &tv2); // sleep
if (retval == -1)
{
throw std::runtime_error(strerror_r(errno, errbuf, SZ));
}
retval = select(ctrl+1, &rfds, &wfds, NULL, &tv);
if (retval == -1)
{
throw std::runtime_error(strerror_r(errno, errbuf, SZ));
}
if (at_file.bad())
{
throw runtime_error("wdm device file gone bad!");
}
if (FD_ISSET(ctrl, &wfds))
{
cout << "Writing command \'" << command << "\' to ctrl device\n";
command += "\r";
at_file << command << endl;
cout << sendcount++;
}
if (FD_ISSET(ctrl, &rfds))
{
n = read(ctrl, ctrlin_buf, SZ); // ifstrem::read fails for
some reason
if (n == -1)
{
throw std::runtime_error(strerror_r(errno, errbuf, SZ));
}
response = std::string(ctrlin_buf, n);
cout << response << endl;
}
}
return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html