📄 gsm0710.c
字号:
break; } } } return returnCode;}char *createSymlinkName(int idx) { if (devSymlinkPrefix == NULL) { return NULL; } char* symLinkName = malloc(strlen(devSymlinkPrefix)+255); sprintf(symLinkName, "%s%d", devSymlinkPrefix, idx); return symLinkName;}int open_pty(char* devname, int idx) { struct termios options; int fd = open(devname, O_RDWR | O_NONBLOCK); char *symLinkName = createSymlinkName(idx); if (fd != -1) { if (symLinkName) { char* ptsSlaveName = ptsname(fd); // Create symbolic device name, e.g. /dev/mux0 unlink(symLinkName); if (symlink(ptsSlaveName, symLinkName) != 0) { syslog(LOG_ERR,"Can't create symbolic link %s -> %s. %s (%d).\n", symLinkName, ptsSlaveName, strerror(errno), errno); } } // get the parameters tcgetattr(fd, &options); // set raw input options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_iflag &= ~(INLCR | ICRNL | IGNCR); // set raw output options.c_oflag &= ~OPOST; options.c_oflag &= ~OLCUC; options.c_oflag &= ~ONLRET; options.c_oflag &= ~ONOCR; options.c_oflag &= ~OCRNL; tcsetattr(fd, TCSANOW, &options); if (strcmp(devname, "/dev/ptmx") == 0) { // Otherwise programs cannot access the pseudo terminals grantpt(fd); unlockpt(fd); } } free(symLinkName); return fd;}/** * Determine baud rate index for CMUX command */int indexOfBaud(int baudrate) { int i; for (i = 0; i < sizeof(baudrates) / sizeof(baudrates[0]); ++i) { if (baudrates[i] == baudrate) return i; } return 0;}/** * Set serial port options. Then switch baudrate to zero for a while * and then back up. This is needed to get some modems * (such as Siemens MC35i) to wake up. */void setAdvancedOptions(int fd, speed_t baud) { struct termios options; struct termios options_cpy; fcntl(fd, F_SETFL, 0); // get the parameters tcgetattr(fd, &options); // Do like minicom: set 0 in speed options cfsetispeed(&options, 0); cfsetospeed(&options, 0); options.c_iflag = IGNBRK; // Enable the receiver and set local mode and 8N1 options.c_cflag = (CLOCAL | CREAD | CS8 | HUPCL); // enable hardware flow control (CNEW_RTCCTS) // options.c_cflag |= CRTSCTS; // Set speed options.c_cflag |= baud; /* options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; // Could this be wrong!?!?!? */ // set raw input options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_iflag &= ~(INLCR | ICRNL | IGNCR); // set raw output options.c_oflag &= ~OPOST; options.c_oflag &= ~OLCUC; options.c_oflag &= ~ONLRET; options.c_oflag &= ~ONOCR; options.c_oflag &= ~OCRNL; // Set the new options for the port... options_cpy = options; tcsetattr(fd, TCSANOW, &options); options = options_cpy; // Do like minicom: set speed to 0 and back options.c_cflag &= ~baud; tcsetattr(fd, TCSANOW, &options); options = options_cpy; sleep(1); options.c_cflag |= baud; tcsetattr(fd, TCSANOW, &options);}/* Opens serial port, set's it to 57600bps 8N1 RTS/CTS mode.** PARAMS:* dev - device name* RETURNS :* file descriptor or -1 on error*/int open_serialport(char *dev){ int fd; if(_debug) syslog(LOG_DEBUG, "is in %s\n" , __FUNCTION__); fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); if (fd != -1) { int index = indexOfBaud(baudrate); if(_debug) syslog(LOG_DEBUG, "serial opened\n" ); if (index > 0) { // Switch the baud rate to zero and back up to wake up // the modem setAdvancedOptions(fd, baud_bits[index]); } else { struct termios options; // The old way. Let's not change baud settings fcntl(fd, F_SETFL, 0); // get the parameters tcgetattr(fd, &options); // Set the baud rates to 57600... // cfsetispeed(&options, B57600); // cfsetospeed(&options, B57600); // Enable the receiver and set local mode... options.c_cflag |= (CLOCAL | CREAD); // No parity (8N1): options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; // enable hardware flow control (CNEW_RTCCTS) // options.c_cflag |= CRTSCTS; // set raw input options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_iflag &= ~(INLCR | ICRNL | IGNCR); // set raw output options.c_oflag &= ~OPOST; options.c_oflag &= ~OLCUC; options.c_oflag &= ~ONLRET; options.c_oflag &= ~ONOCR; options.c_oflag &= ~OCRNL; // Set the new options for the port... tcsetattr(fd, TCSANOW, &options); } } return fd;}// Prints information on a framevoid print_frame(GSM0710_Frame * frame){ if(_debug) { syslog(LOG_DEBUG, "is in %s\n" , __FUNCTION__); syslog(LOG_DEBUG,"Received "); } switch((frame->control & ~PF)) { case SABM: if(_debug) syslog(LOG_DEBUG,"SABM "); break; case UIH: if(_debug) syslog(LOG_DEBUG,"UIH "); break; case UA: if(_debug) syslog(LOG_DEBUG,"UA "); break; case DM: if(_debug) syslog(LOG_DEBUG,"DM "); break; case DISC: if(_debug) syslog(LOG_DEBUG,"DISC "); break; case UI: if(_debug) syslog(LOG_DEBUG,"UI "); break; default: if(_debug) syslog(LOG_DEBUG,"unkown (control=%d) ", frame->control); break; } if(_debug) syslog(LOG_DEBUG," frame for channel %d.\n", frame->channel); if (frame->data_length > 0) { if(_debug) { syslog(LOG_DEBUG,"frame->data = %s / size = %d\n",frame->data, frame->data_length); //fwrite(frame->data, sizeof(char), frame->data_length, stdout); syslog(LOG_DEBUG,"\n"); } }}/* Handles commands received from the control channel.*/void handle_command(GSM0710_Frame * frame){#if 1 unsigned char type, signals; int length = 0, i, type_length, channel, supported = 1; unsigned char *response; // struct ussp_operation op; if(_debug) syslog(LOG_DEBUG, "is in %s\n" , __FUNCTION__); if (frame->data_length > 0) { type = frame->data[0]; // only a byte long types are handled now // skip extra bytes for (i = 0; (frame->data_length > i && (frame->data[i] & EA) == 0); i++); i++; type_length = i; if ((type & CR) == CR) { // command not ack // extract frame length while (frame->data_length > i) { length = (length * 128) + ((frame->data[i] & 254) >> 1); if ((frame->data[i] & 1) == 1) break; i++; } i++; switch((type & ~CR)) { case C_CLD: syslog(LOG_INFO,"The mobile station requested mux-mode termination.\n"); if (faultTolerant) { // Signal restart restart = 1; } else { terminate = 1; terminateCount = -1; // don't need to close down channels } break; case C_TEST: #ifdef DEBUG if(_debug) syslog(LOG_DEBUG,"Test command: "); if(_debug) syslog(LOG_DEBUG,"frame->data = %s / frame->data_length = %d\n",frame->data + i, frame->data_length - i); //fwrite(frame->data + i, sizeof(char), frame->data_length - i, stdout); #endif break; case C_MSC: if (i + 1 < frame->data_length) { channel = ((frame->data[i] & 252) >> 2); i++; signals = (frame->data[i]); // op.op = USSP_MSC; // op.arg = USSP_RTS; // op.len = 0; if(_debug) syslog(LOG_DEBUG,"Modem status command on channel %d.\n", channel); if ((signals & S_FC) == S_FC) { if(_debug) syslog(LOG_DEBUG,"No frames allowed.\n"); } else { // op.arg |= USSP_CTS; if(_debug) syslog(LOG_DEBUG,"Frames allowed.\n"); } if ((signals & S_RTC) == S_RTC) { // op.arg |= USSP_DSR; if(_debug) syslog(LOG_DEBUG,"RTC\n"); } if ((signals & S_IC) == S_IC) { // op.arg |= USSP_RI; if(_debug) syslog(LOG_DEBUG,"Ring\n"); } if ((signals & S_DV) == S_DV) { // op.arg |= USSP_DCD; if(_debug) syslog(LOG_DEBUG,"DV\n"); } // if (channel > 0) // write(ussp_fd[(channel - 1)], &op, sizeof(op)); } else { syslog(LOG_ERR,"ERROR: Modem status command, but no info. i: %d, len: %d, data-len: %d\n", i, length, frame->data_length); } break; default: syslog(LOG_ALERT,"Unknown command (%d) from the control channel.\n", type); response = malloc(sizeof(char) * (2 + type_length)); response[0] = C_NSC; // supposes that type length is less than 128 response[1] = EA & ((127 & type_length) << 1); i = 2; while (type_length--) { response[i] = frame->data[(i - 2)]; i++; } write_frame(0, response, i, UIH); free(response); supported = 0; break; } if (supported) { // acknowledge the command frame->data[0] = frame->data[0] & ~CR; write_frame(0, frame->data, frame->data_length, UIH); } } else { // received ack for a command if (COMMAND_IS(C_NSC, type)) { syslog(LOG_ALERT,"The mobile station didn't support the command sent.\n"); } else { if(_debug) syslog(LOG_DEBUG,"Command acknowledged by the mobile station.\n"); } } }#endif}// shows how to use this programvoid usage(char *_name){ fprintf(stderr,"\nUsage: %s [options] <pty1> <pty2> ...\n",_name); fprintf(stderr," <ptyN> : pty devices (e.g. /dev/ptya0)\n\n"); fprintf(stderr,"options:\n"); fprintf(stderr," -p <serport> : Serial port device to connect to [/dev/modem]\n"); fprintf(stderr," -f <framsize> : Maximum frame size [32]\n"); fprintf(stderr," -d : Debug mode, don't fork\n"); fprintf(stderr," -m <modem> : Modem (mc35, mc75, generic, ...)\n"); fprintf(stderr," -b <baudrate> : MUX mode baudrate (0,9600,19200, ...)\n"); fprintf(stderr," -P <PIN-code> : PIN code to fed to the modem\n"); fprintf(stderr," -s <symlink-prefix> : Prefix for the symlinks of slave devices (e.g. /dev/mux)\n"); fprintf(stderr," -w : Wait for deamon startup success/failure\n"); fprintf(stderr," -r : Restart automatically if the modem stops responding\n"); fprintf(stderr," -h : Show this help message\n");}/* Extracts and handles frames from the receiver buffer.** PARAMS:* buf - the receiver buffer*/int extract_frames(GSM0710_Buffer * buf){ // version test for Siemens terminals to enable version 2 functions static char version_test[] = "\x23\x21\x04TEMUXVERSION2\0\0"; int framesExtracted = 0; GSM0710_Frame *frame; if(_debug) syslog(LOG_DEBUG, "is in %s\n" , __FUNCTION__); while ((frame = gsm0710_buffer_get_frame(buf))) { ++framesExtracted; if ((FRAME_IS(UI, frame) || FRAME_IS(UIH, frame))) { if(_debug) syslog(LOG_DEBUG, "is (FRAME_IS(UI, frame) || FRAME_IS(UIH, frame))\n"); if (frame->channel > 0) { if(_debug) syslog(LOG_DEBUG,"frame->channel > 0\n"); // data from logical channel ussp_send_data(frame->data, frame->data_length, frame->channel - 1); } else { // control channel command if(_debug) syslog(LOG_DEBUG,"control channel command\n"); handle_command(frame); } } else { // not an information frame if(_debug) syslog(LOG_DEBUG,"not an information frame\n");#ifdef DEBUG print_frame(frame);#endif switch((frame->control & ~PF)) { case UA: if(_debug) syslog(LOG_DEBUG,"is FRAME_IS(UA, frame)\n"); if (cstatus[frame->channel].opened == 1) { syslog(LOG_INFO,"Logical channel %d closed.\n", frame->channel); cstatus[frame->channel].opened = 0; } else { cstatus[frame->channel].opened = 1; if (frame->channel == 0) { syslog(LOG_INFO,"Control channel opened.\n"); // send version Siemens version test write_frame(0, version_test, 18, UIH); } else { syslog(LOG_INFO,"Logical channel %d opened.\n", frame->channel); } } break; case DM: if (cstatus[frame->channel].opened) { syslog(LOG_INFO,"DM received, so the channel %d was already closed.\n", frame->channel); cstatus[frame->channel].opened = 0; } else { if (frame->channel == 0) { syslog(LOG_INFO,"Couldn't open control channel.\n->Terminating.\n"); terminate = 1; terminateCount = -1; // don't need to close channels } else { syslog(LOG_INFO,"Logical channel %d couldn't be opened.\n", frame->channel); } } break; case DISC: if (cstatus[frame->channel].opened) { cstatus[frame->channel].opened = 0; write_frame(frame->channel, NULL, 0, UA | PF); if (frame->channel == 0) { syslog(LOG_INFO,"Control channel closed.\n"); if (faultTolerant) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -