Index: common/links/atbus.c =================================================================== RCS file: /sources/gnokii/gnokii/common/links/atbus.c,v retrieving revision 1.49 diff -u -p -r1.49 atbus.c --- common/links/atbus.c 26 Apr 2006 20:07:30 -0000 1.49 +++ common/links/atbus.c 5 Jul 2007 21:12:29 -0000 @@ -177,6 +177,8 @@ static void atbus_rx_statemachine(unsign /* if not found, start at buffer beginning */ if (!start) start = bi->rbuf+1; + + fprintf (stdout, "LINE: %s\n", start); /* there are certainly more that 2 chars in buffer */ if (!strncmp(start, "OK", 2)) bi->rbuf[0] = GN_AT_OK; @@ -219,6 +221,12 @@ static void atbus_rx_statemachine(unsign else if (!strncmp(start + 1, "CRING:", 6)) { sm_incoming_function(GN_OP_AT_Ring, start, bi->rbuf_pos - 1 - (start - bi->rbuf), sm); unsolicited = 1; + } else if (!strncmp(start + 1, "CLIP:", 5)) { + sm_incoming_function(GN_OP_AT_Ring, start, bi->rbuf_pos - 1 - (start - bi->rbuf), sm); + unsolicited = 1; + } else if (!strncmp(start + 1, "CLCC:", 5)) { + sm_incoming_function(GN_OP_AT_Ring, start, bi->rbuf_pos - 1 - (start - bi->rbuf), sm); + unsolicited = 1; } } if (unsolicited) { Index: common/phones/atgen.c =================================================================== RCS file: /sources/gnokii/gnokii/common/phones/atgen.c,v retrieving revision 1.144 diff -u -p -r1.144 atgen.c --- common/phones/atgen.c 5 Jul 2007 19:55:25 -0000 1.144 +++ common/phones/atgen.c 5 Jul 2007 21:12:30 -0000 @@ -1130,9 +1130,20 @@ static gn_error AT_SetCallNotification(g return GN_ERR_NOTREADY; if ((err = sm_block_no_retry(GN_OP_SetCallNotification, data, state)) != GN_ERR_NONE) return err; + if (sm_message_send(10, GN_OP_SetCallNotification, "AT+CLIP=1\r", state)) + return GN_ERR_NOTREADY; + /* Ignore errors when we can't set Call Line Identity, just set that we + * don't handle it */ + if (sm_block_no_retry(GN_OP_SetCallNotification, data, state) == GN_ERR_NONE) + drvinst->clip_supported = 1; + if (sm_message_send(10, GN_OP_SetCallNotification, "AT+CLCC=1\r", state)) + return GN_ERR_NOTREADY; + /* Ignore errors when we can't set List Current Calls notifications */ + sm_block_no_retry(GN_OP_SetCallNotification, data, state); } drvinst->call_notification = data->call_notification; + drvinst->call_notification_user_data = data->user_data; return GN_ERR_NONE; } @@ -1564,33 +1575,33 @@ static gn_error ReplyGetSMS(int messaget return GN_ERR_INTERNALERROR; /* Try to figure out the status first */ - tmp = strchr(buf.line2, ','); - if (tmp != NULL && ((char *) tmp - buf.line2 - strlen("+CMGR: ")) >= 1) { + tmp = strchr (buf.line2, ','); + if (tmp != NULL && ((char *) tmp - buf.line2 - strlen ("+CMGR: ")) >= 1) { char *status; int len; - len = (char *) tmp - buf.line2 - strlen("+CMGR: "); - status = malloc(len + 1); + len = (char *) tmp - buf.line2 - strlen ("+CMGR: "); + status = malloc (len + 1); if (!status) { dprintf("Not enough memory for buffer.\n"); return GN_ERR_INTERNALERROR; } - memcpy(status, buf.line2 + strlen("+CMGR: "), len); + memcpy (status, buf.line2 + strlen ("+CMGR: "), len); status[len] = '\0'; - if (strstr(status, "UNREAD")) { + if (strstr (status, "UNREAD") != NULL) { data->raw_sms->status = GN_SMS_Unread; - } else if (strstr(status, "READ")) { + } else if (strstr (status, "READ") != NULL) { data->raw_sms->status = GN_SMS_Read; - } else if (strstr(status, "UNSENT")) { + } else if (strstr (status, "UNSENT") != NULL) { data->raw_sms->status = GN_SMS_Unsent; - } else if (strstr(status, "SENT")) { + } else if (strstr (status, "SENT") != NULL) { data->raw_sms->status = GN_SMS_Sent; } else { int s; - s = atoi(status); + s = atoi (status); switch (s) { case 0: data->raw_sms->status = GN_SMS_Unread; @@ -1770,6 +1781,7 @@ static gn_error ReplyRing(int messagetyp at_line_buffer buf; char *pos; gn_call_info cinfo; + gn_call_status status; if (!drvinst->call_notification) return GN_ERR_UNSOLICITED; @@ -1780,35 +1792,161 @@ static gn_error ReplyRing(int messagetyp memset(&cinfo, 0, sizeof(cinfo)); cinfo.call_id = 1; - if (!strncmp(buf.line1, "RING", 4)) + if (!strncmp(buf.line1, "RING", 4)) { return GN_ERR_INTERNALERROR; /* AT+CRC=1 disables RING */ - - else if (!strncmp(buf.line1, "+CRING: ", 8)) { + } else if (!strncmp(buf.line1, "+CRING: ", 8)) { pos = buf.line1 + 8; if (!strncmp(pos, "VOICE", 5)) cinfo.type = GN_CALL_Voice; else return GN_ERR_UNHANDLEDFRAME; - drvinst->call_notification(GN_CALL_Incoming, &cinfo, state); - - } else if (!strncmp(buf.line1, "CONNECT", 7)) - drvinst->call_notification(GN_CALL_Established, &cinfo, state); + status = GN_CALL_Incoming; + } else if (!strncmp(buf.line1, "CONNECT", 7)) { + status = GN_CALL_Established; + } else if (!strncmp(buf.line1, "BUSY", 4)) { + status = GN_CALL_RemoteHangup; + } else if (!strncmp(buf.line1, "NO ANSWER", 9)) { + status = GN_CALL_RemoteHangup; + } else if (!strncmp(buf.line1, "NO CARRIER", 10)) { + status = GN_CALL_RemoteHangup; + } else if (!strncmp(buf.line1, "NO DIALTONE", 11)) { + status = GN_CALL_LocalHangup; + } else if (!strncmp(buf.line1, "+CLIP: ", 7)) { + char **items; + int i; + + items = gnokii_strsplit(buf.line1 + 7, ",", 6); + for (i = 0; i < 6; i++) { + if (items[i] == NULL) + break; + switch (i) { + /* Number, if known */ + case 0: + snprintf (cinfo.number, GN_PHONEBOOK_NUMBER_MAX_LENGTH, "%s", strip_quotes (items[i])); + break; + /* 1 == Number "type" + * 2 == String type subaddress + * 3 == Type of subaddress + * All ignored + */ + case 1: + case 2: + case 3: + break; + /* Name, if known */ + case 4: + snprintf (cinfo.name, GN_PHONEBOOK_NAME_MAX_LENGTH, "%s", strip_quotes (items[i])); + break; + /* Validity of the name/number provided */ + case 5: + switch (atoi (items[i])) { + case 1: + snprintf (cinfo.name, GN_PHONEBOOK_NAME_MAX_LENGTH, "Withheld"); + break; + case 2: + snprintf (cinfo.name, GN_PHONEBOOK_NAME_MAX_LENGTH, "Unknown"); + break; + } + } + } - else if (!strncmp(buf.line1, "BUSY", 4)) - drvinst->call_notification(GN_CALL_RemoteHangup, &cinfo, state); + if (cinfo.name == NULL) + snprintf (cinfo.name, GN_PHONEBOOK_NAME_MAX_LENGTH, "Unknown"); + cinfo.type = drvinst->last_call_type; + drvinst->call_notification(drvinst->last_call_status, &cinfo, state, drvinst->call_notification_user_data); + gnokii_strfreev (items); + return GN_ERR_UNSOLICITED; + } else if (!strncmp(buf.line1, "+CLCC: ", 7)) { + char **items; + int i; - else if (!strncmp(buf.line1, "NO ANSWER", 9)) - drvinst->call_notification(GN_CALL_RemoteHangup, &cinfo, state); + items = gnokii_strsplit(buf.line1 + 7, ",", 8); + status = -1; - else if (!strncmp(buf.line1, "NO CARRIER", 10)) - drvinst->call_notification(GN_CALL_RemoteHangup, &cinfo, state); + for (i = 0; i < 8; i++) { + if (items[i] == NULL) + break; + switch (i) { + /* Call ID */ + case 0: + cinfo.call_id = atoi (items[i]); + break; + /* Incoming, or finishing call */ + case 1: + break; + case 2: + switch (atoi (items[i])) { + case 0: + status = GN_CALL_Established; + break; + case 1: + //FIXME Held call + break; + case 2: + //FIXME dialing + break; + case 3: + //FIXME alerting + break; + case 4: + status = GN_CALL_Incoming; + break; + case 5: + //FIXME waiting + break; + case 6: + status = GN_CALL_LocalHangup; + break; + } + break; + case 3: + if (atoi (items[i]) == 0) + cinfo.type = GN_CALL_Voice; + else { + /* We don't handle non-voice calls */ + gnokii_strfreev (items); + return GN_ERR_UNHANDLEDFRAME; + } + break; + /* Multiparty status */ + case 4: + break; + case 5: + snprintf (cinfo.number, GN_PHONEBOOK_NUMBER_MAX_LENGTH, "%s", strip_quotes (items[i])); + break; + /* Phone display format */ + case 6: + break; + case 7: + snprintf (cinfo.name, GN_PHONEBOOK_NAME_MAX_LENGTH, "%s", strip_quotes (items[i])); + break; + } + } - else if (!strncmp(buf.line1, "NO DIALTONE", 11)) - drvinst->call_notification(GN_CALL_LocalHangup, &cinfo, state); + /* FIXME we don't handle calls > 1 anywhere else */ + if (cinfo.call_id > 1) { + gnokii_strfreev (items); + return GN_ERR_UNHANDLEDFRAME; + } + if (status < 0) { + gnokii_strfreev (items); + return GN_ERR_UNHANDLEDFRAME; + } - else + drvinst->call_notification(status, &cinfo, state, drvinst->call_notification_user_data); + gnokii_strfreev (items); + return GN_ERR_UNSOLICITED; + } else { return GN_ERR_UNHANDLEDFRAME; + } + + if (!drvinst->clip_supported || status != GN_CALL_Incoming) { + drvinst->call_notification(status, &cinfo, state, drvinst->call_notification_user_data); + } else { + drvinst->last_call_status = status; + drvinst->last_call_type = cinfo.type; + } return GN_ERR_UNSOLICITED; } @@ -1981,6 +2119,10 @@ static gn_error Initialise(gn_data *setu drvinst->charset = AT_CHAR_UNKNOWN; drvinst->no_smsc = 0; drvinst->call_notification = NULL; + drvinst->call_notification_user_data = NULL; + drvinst->clip_supported = 0; + drvinst->last_call_type = GN_CALL_Voice; + drvinst->last_call_status = GN_CALL_Idle; drvinst->if_pos = 0; for (i = 0; i < GN_OP_AT_Max; i++) { Index: include/phones/atgen.h =================================================================== RCS file: /sources/gnokii/gnokii/include/phones/atgen.h,v retrieving revision 1.23 diff -u -p -r1.23 atgen.h --- include/phones/atgen.h 14 Apr 2007 19:36:35 -0000 1.23 +++ include/phones/atgen.h 5 Jul 2007 21:12:35 -0000 @@ -80,7 +80,12 @@ typedef struct { at_charset defaultcharset; at_charset charset; - void (*call_notification)(gn_call_status call_status, gn_call_info *call_info, struct gn_statemachine *state); + int clip_supported; + gn_call_type last_call_type; + gn_call_status last_call_status; + + void (*call_notification)(gn_call_status call_status, gn_call_info *call_info, struct gn_statemachine *state, void *user_data); + void *call_notification_user_data; } at_driver_instance; #define AT_DRVINST(s) (*((at_driver_instance **)(&(s)->driver.driver_instance)))