I'm posting the code below based on some testing I was doing with the Conexant USB CX93010. The code below is in C (rather than C#) and runs on Linux (rather than Windows). But it should provide a good baseline for a C# program.
The code is based on another Stack Overflow answer written by Sawdust, and it has test results from the program.
You can also find a comprehensive AT command set for Conexant modems at http://www.arcelect.com. It is dated from 2001, but it has more AT commands for the modems than I found elsewhere on the web.
Here is the code.
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#define DISPLAY_STRING 1
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfmakeraw (&tty);
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
void write_command(int fd, const void* cmd, size_t len)
{
if (len == ~(size_t)0)
len = strlen((const char*)cmd);
printf("Send %d: %s\n", (int)len, (const char*)cmd);
int wlen = write(fd, cmd, len);
if (wlen != len) {
printf("Error from write: %d, %d\n", wlen, errno);
}
tcdrain(fd); /* delay for output */
}
void read_response(int fd)
{
char buf[256];
int rlen = read(fd, buf, sizeof(buf) - 1);
if (rlen > 0) {
#ifdef DISPLAY_STRING
buf[rlen] = 0;
printf("Read %d: \"%s\"\n", rlen, buf);
#else /* display hex */
unsigned char *p;
printf("Read %d:", rlen);
for (p = buf; rlen-- > 0; p++)
printf(" 0x%x", *p);
printf("\n");
#endif
} else if (rlen < 0) {
printf("Error from read: %d: %s\n", rlen, strerror(errno));
} else { /* rlen == 0 */
printf("Timeout from read\n");
}
}
int main(int argc, char* argv[])
{
int fd;
const char portname[] = "/dev/ttyACM0";
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("Error opening %s: %s\n", portname, strerror(errno));
return -1;
}
/*baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B115200);
write_command(fd, "ATZ\r", 4); /* Reset */
read_response(fd);
write_command(fd, "ATE0\r", -1); /* Echo off */
read_response(fd);
write_command(fd, "AT+VCID=?\r", -1); /* Query CallerID caps */
read_response(fd);
write_command(fd, "AT+CLIP=?\r", -1); /* Query CallerID caps */
read_response(fd);
write_command(fd, "AT+VCID=1\r", -1); /* Set CallerID */
read_response(fd);
printf("Entering loop, CTRL+C to break...\n\n");
while (1)
{
read_response(fd);
}
return 0;
}
Here are the test results using a cell phone. I changed the name and phone number; other wise it is the exact output of the program.
$ sudo ./modem.exe
Send 4: ATZ
Read 6: "
OK
"
Send 5: ATE0
Read 11: "ATE0
OK
"
Send 10: AT+VCID=?
Read 15: "
(0-2)
OK
"
Send 10: AT+CLIP=?
Read 9: "
ERROR
"
Send 10: AT+VCID=1
Read 6: "
OK
"
Entering loop, CTRL+C to break...
Read 8: "
RING
"
Read 67: "
DATE = 0214
TIME = 2116
NMBR = 2025551212
NAME = JANE DOE
"
Read 8: "
RING
"
Read 67: "
DATE = 0214
TIME = 2116
NMBR = 2025551212
NAME = JANE DOE
"
Read 8: "
RING
"
Read 8: "
RING
"
Read 8: "
RING
"
Also, you can send an AT+GSR
to get the real modem revision instead of what Windows provides (which appears to be a little inaccurate):
Send 7: AT+GMR
Read 44: "AT+GMR
+GMR: CX93001-EIS_V0.2013-V92
OK"