📄 smsc_at2.c
字号:
} /* Set the modem to PDU mode and autodisplay of new messages */ ret = at2_send_modem_command(privdata, "AT+CMGF=0", 0, 0); if (ret != 0 ) return -1; /* lets see if it supports GSM SMS 2+ mode */ ret = at2_send_modem_command(privdata, "AT+CSMS=?", 0, 0); if (ret != 0) { /* if it doesnt even understand the command, I'm sure it wont support it */ privdata->phase2plus = 0; } else { /* we have to take a part a string like +CSMS: (0,1,128) */ Octstr *ts; int i; List *vals; ts = privdata->lines; privdata->lines = NULL; i = octstr_search_char(ts, '(', 0); if (i > 0) { octstr_delete(ts, 0, i + 1); } i = octstr_search_char(ts, ')', 0); if (i > 0) { octstr_truncate(ts, i); } vals = octstr_split(ts, octstr_imm(",")); octstr_destroy(ts); ts = list_search(vals, octstr_imm("1"), (void*) octstr_item_match); if (ts) privdata->phase2plus = 1; list_destroy(vals, octstr_destroy_item); } if (privdata->phase2plus) { info(0, "AT2[%s]: Phase 2+ is supported", octstr_get_cstr(privdata->name)); ret = at2_send_modem_command(privdata, "AT+CSMS=1", 0, 0); if (ret != 0) return -1; } /* send init string */ ret = at2_send_modem_command(privdata, octstr_get_cstr(privdata->modem->init_string), 0, 0); if (ret != 0) return -1; if (privdata->sms_memory_poll_interval && privdata->modem->message_storage) { /* set message storage location for "SIM buffering" using the CPMS command */ Octstr *temp; temp = octstr_create("AT+CPMS="); octstr_append_char(temp, 34); octstr_append(temp, privdata->modem->message_storage); octstr_append_char(temp, 34); ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0); octstr_destroy(temp); if (ret != 0) return -1; } info(0, "AT2[%s]: AT SMSC successfully opened.", octstr_get_cstr(privdata->name)); return 0;}int at2_send_modem_command(PrivAT2data *privdata, char *cmd, time_t timeout, int gt_flag){ at2_write_line(privdata, cmd); return at2_wait_modem_command(privdata, timeout, gt_flag, NULL);}int at2_wait_modem_command(PrivAT2data *privdata, time_t timeout, int gt_flag, int *output){ Octstr *line = NULL; Octstr *line2 = NULL; Octstr *pdu = NULL; int ret; time_t end_time; time_t cur_time; Msg *msg; int len; int cmgr_flag = 0; time(&end_time); if (timeout == 0) timeout = 3; end_time += timeout; if (privdata->lines != NULL) octstr_destroy(privdata->lines); privdata->lines = octstr_create(""); while (time(&cur_time) <= end_time) { O_DESTROY(line); line = at2_read_line(privdata, gt_flag); if (line) { octstr_append(privdata->lines, line); octstr_append_cstr(privdata->lines, "\n"); if (octstr_search(line, octstr_imm("SIM PIN"), 0) != -1) { ret = 2; goto end; } if (octstr_search(line, octstr_imm("OK"), 0) != -1) { ret = 0; goto end; } if ((gt_flag ) && (octstr_search(line, octstr_imm(">"), 0) != -1)) { ret = 1; goto end; } if (octstr_search(line, octstr_imm("RING"), 0) != -1) { at2_write_line(privdata, "ATH0"); continue; } if (octstr_search(line, octstr_imm("+CPIN: READY"), 0) != -1) { privdata->pin_ready = 1; continue; } if ( -1 != octstr_search(line, octstr_imm("+CMS ERROR"), 0)) { error(0, "AT2[%s]: CMS ERROR: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(line)); ret = 1; goto end; } if (octstr_search(line, octstr_imm("+CMT:"), 0) != -1 || octstr_search(line, octstr_imm("+CDS:"), 0) != -1 || ((octstr_search(line, octstr_imm("+CMGR:"), 0) != -1) && (cmgr_flag = 1)) ) { line2 = at2_wait_line(privdata, 1, 0); if (line2 == NULL) { error(0, "AT2[%s]: got +CMT but waiting for next line timed out", octstr_get_cstr(privdata->name)); } else { octstr_append_cstr(line, "\n"); octstr_append(line, line2); O_DESTROY(line2); at2_pdu_extract(privdata, &pdu, line); if (pdu == NULL) { error(0, "AT2[%s]: got +CMT but pdu_extract failed", octstr_get_cstr(privdata->name)); } else { /* count message even if I can't decode it */ if (output) ++(*output); msg = at2_pdu_decode(pdu, privdata); if (msg != NULL) { msg->sms.smsc_id = octstr_duplicate(privdata->conn->id); bb_smscconn_receive(privdata->conn, msg); } if (!cmgr_flag) { if (privdata->phase2plus) at2_write_line(privdata, "AT+CNMA"); } O_DESTROY(pdu); } } continue; } if ((octstr_search(line, octstr_imm("+CMGS:"),0) != -1) && (output)) { /* found response to a +CMGS command, read the message id and return it in output */ long temp; if (octstr_parse_long(&temp, line, octstr_search(line, octstr_imm("+CMGS:"),0)+6,10) == -1) error(0,"AT2[%s]: got +CMGS but failed to read message id", octstr_get_cstr(privdata->name)); else *output = temp; } if ( -1 != octstr_search(line, octstr_imm("ERROR"), 0)) { ret = -1; goto end; } } } len = octstr_len(privdata->ilb); /* error(0,"AT2[%s]: timeout. received <%s> until now, buffer size is %d, buf=%s", octstr_get_cstr(privdata->name), privdata->lines ? octstr_get_cstr(privdata->lines) : "<nothing>", len, privdata->ilb ? octstr_get_cstr(privdata->ilb) : "<nothing>"); */ O_DESTROY(line); O_DESTROY(line2); O_DESTROY(pdu); return -1; /* timeout */end: octstr_append(privdata->lines, line); octstr_append_cstr(privdata->lines, "\n"); O_DESTROY(line); O_DESTROY(line2); O_DESTROY(pdu); return ret;}void at2_read_sms_memory(PrivAT2data* privdata){ char cmd[20]; /* get memory status */ if (at2_check_sms_memory(privdata) == -1) { debug("bb.smsc.at2", 0, "AT2[%s]: memory check error", octstr_get_cstr(privdata->name)); return ; } if (privdata->sms_memory_usage) { /* * that is - greater then 0, meaning there are some messages to fetch * now - I used to just loop over the first input_mem_sms_used locations, * but it doesn't hold, since under load, messages may be received while * we're in the loop, and get stored in locations towards the end of the list, * thus creating 'holes' in the memory. * * There are two ways we can fix this : * (a) Just read the last message location, delete it and return. * It's not a complete solution since holes can still be created if messages * are recieved between the memory check and the delete command, * and anyway - it will slow us down and won't hold well under pressure * (b) Just scan the entire memory each call, bottom to top. * This will be slow too, but it'll be reliable. * * We can massivly improve performance by stopping after input_mem_sms_used messages * have been read, but send_modem_command returns 0 for no message as well as for a * message read, and the only other way to implement it is by doing memory_check * after each read and stoping when input_mem_sms_used get to 0. This is slow * (modem commands take time) so we improve speed only if there are less then 10 * messages in memory. * * I implemented the alternative - changed at2_wait_modem_command to return the * number of messages it collected. */ int i; int message_count = 0; /* cound number of messages collected */ debug("bb.smsc.at2", 0, "AT2[%s]: %d messages waiting in memory", octstr_get_cstr(privdata->name), privdata->sms_memory_usage); /* * loop till end of memory or collected enouch messages */ for (i = 1; i <= privdata->sms_memory_capacity && message_count < privdata->sms_memory_usage; ++i) { int old_message_count = message_count; sprintf(cmd, "AT+CMGR=%d", i); /* read one message from memory */ at2_write_line(privdata, cmd); if (at2_wait_modem_command(privdata, 0, 0, &message_count) != 0) { debug("bb.smsc.at2", 0, "AT2[%s]: failed to get message %d.", octstr_get_cstr(privdata->name), i); continue; /* failed to read the message - skip to next message */ } /* no need to delete if no message collected */ if (old_message_count == message_count) { debug("bb.smsc.at2", 0, "AT2[%s]: not deleted.", octstr_get_cstr(privdata->name)); continue; } sprintf(cmd, "AT+CMGD=%d", i); /* delete the message we just read */ /* * 3 seconds is not enough with some modems if the message is large, * so we'll give it 7 seconds */ if (at2_send_modem_command(privdata, cmd, 7, 0) != 0) { /* * failed to delete the message, we'll just ignore it for now, * this is bad, since if the message really didn't get deleted * we'll see it next time around. */ debug("bb.smsc.at2", 0, "AT2[%s]: failed to delete message %d.", octstr_get_cstr(privdata->name), i); continue; } } } /* at2_send_modem_command(privdata, ModemTypes[privdata->modemid].init1, 0, 0); */}int at2_check_sms_memory(PrivAT2data *privdata){ long values[4]; /* array to put response data in */ int pos; /* position of parser in data stream */ int ret; Octstr* search_cpms = NULL; /* select memory type and get report */ if ((ret = at2_send_modem_command(privdata, "AT+CPMS?", 0, 0)) != 0) { debug("bb.smsc.at2.memory_check", 0, "failed to send mem select command to modem %d", ret); return -1; } search_cpms = octstr_create("+CPMS:"); if ((pos = octstr_search(privdata->lines, search_cpms, 0)) != -1) { /* got back a +CPMS response */ int index = 0; /* index in values array */ pos += 6; /* position of parser in the stream - start after header */ /* skip memory indication */ pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1; /* find all the values */ while (index < 4 && pos < octstr_len(privdata->lines) && (pos = octstr_parse_long(&values[index], privdata->lines, pos, 10)) != -1) { ++pos; /* skip number seperator */ ++index; /* increment array index */ if (index == 2) /* skip second memory indication */ pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1; } if (index < 4) { /* didn't get all memory data - I don't why, so I'll bail */ debug("bb.smsc.at2", 0, "AT2[%s]: couldn't parse all memory locations : %d:'%s'.", octstr_get_cstr(privdata->name), index, &(octstr_get_cstr(privdata->lines)[pos])); O_DESTROY(search_cpms); return -1; } privdata->sms_memory_usage = values[0]; privdata->sms_memory_capacity = values[1]; /* privdata->output_mem_sms_used = values[2]; privdata->output_mem_sms_capacity = values[3]; */ /* everything's cool */ ret = 0; /* clear the buffer */ O_DESTROY(privdata->lines); } else { debug("bb.smsc.at2", 0, "AT2[%s]: no correct header for CPMS response.", octstr_get_cstr(privdata->name)); /* didn't get a +CPMS response - this is clearly an error */ ret = -1; } O_DESTROY(search_cpms); return ret;}void at2_set_speed(PrivAT2data *privdata, int bps){ struct termios tios; int ret; int speed; tcgetattr(privdata->fd, &tios); switch (bps) { case 300: speed = B300; break; case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break;#ifdef B57600 case 57600: speed = B57600; break;#endif default: speed = B9600; } cfsetospeed(&tios, speed); cfsetispeed(&tios, speed); ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */ if (ret == -1) { error(errno, "AT2[%s]: at_data_link: fail to set termios attribute", octstr_get_cstr(privdata->name)); } tcflush(privdata->fd, TCIOFLUSH); info(0, "AT2[%s]: speed set to %d", octstr_get_cstr(privdata->name), bps);}void at2_device_thread(void *arg)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -