Send commitlog mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://lists.openmoko.org/mailman/listinfo/commitlog
or, via email, send a message with subject or body 'help' to
        [EMAIL PROTECTED]

You can reach the person managing the list at
        [EMAIL PROTECTED]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of commitlog digest..."
Today's Topics:

   1. r3760 - in trunk/src/target/gsm: include/gsmd include/libgsmd
      src/gsmd src/libgsmd src/util ([EMAIL PROTECTED])
--- Begin Message ---
Author: erin_yueh
Date: 2008-01-03 10:13:39 +0100 (Thu, 03 Jan 2008)
New Revision: 3760

Modified:
   trunk/src/target/gsm/include/gsmd/usock.h
   trunk/src/target/gsm/include/libgsmd/voicecall.h
   trunk/src/target/gsm/src/gsmd/usock.c
   trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c
   trunk/src/target/gsm/src/util/shell.c
Log:
gsmd: add Call Forwarding function (Sean Chiang)



Modified: trunk/src/target/gsm/include/gsmd/usock.h
===================================================================
--- trunk/src/target/gsm/include/gsmd/usock.h   2008-01-02 08:37:09 UTC (rev 
3759)
+++ trunk/src/target/gsm/include/gsmd/usock.h   2008-01-03 09:13:39 UTC (rev 
3760)
@@ -43,6 +43,11 @@
        GSMD_VOICECALL_VOL_GET  = 6,
        GSMD_VOICECALL_GET_STAT = 7,
        GSMD_VOICECALL_CTRL     = 8,
+       GSMD_VOICECALL_FWD_DIS  = 9,
+       GSMD_VOICECALL_FWD_EN   = 10,
+       GSMD_VOICECALL_FWD_STAT = 11,
+       GSMD_VOICECALL_FWD_REG  = 12,
+       GSMD_VOICECALL_FWD_ERAS = 13,
 };
 
 
@@ -99,6 +104,22 @@
        GSMD_CALL_CTRL_M_HELD                   = 6,    // 3
 };
 
+/* call forward reason from 3GPP TS 07.07 subclause 07.10 */
+enum gsmd_call_fwd_reason {
+       GSMD_CALL_FWD_REASON_UNCOND             = 0,
+       GSMD_CALL_FWD_REASON_BUSY               = 1, 
+       GSMD_CALL_FWD_REASON_NO_REPLY           = 2,
+       GSMD_CALL_FWD_REASON_NOT_REACHABLE      = 3,
+       GSMD_CALL_FWD_REASON_ALL_FORWARD        = 4,
+       GSMD_CALL_FWD_REASON_ALL_COND_FORWARD   = 5, 
+};
+
+/* call forward status from 3GPP TS 07.07 subclause 07.10 */
+enum gsmd_call_fwd_status {
+       GSMD_CALL_FWD_STATUS_NOT_ACTIVE = 0,
+       GSMD_CALL_FWD_STATUS_ACTIVE     = 1,
+};
+
 /* Handset / MT related commands */
 enum gsmd_msg_phone_type {
        GSMD_PHONE_VOLUME       = 1,
@@ -384,6 +405,23 @@
        u_int8_t idx;
 } __attribute__ ((packed));
 
+/* call forwarding register from 3GPP TS 07.07 clause 7.10 */
+struct gsmd_call_fwd_reg {
+       enum gsmd_call_fwd_reason reason;
+       struct gsmd_addr addr;
+} __attribute__ ((packed));
+
+/* status of call forwarding from 3GPP TS 07.07 clause 7.10 */
+struct gsmd_call_fwd_stat {
+       enum gsmd_call_fwd_status status; 
+       u_int8_t classx;
+       struct gsmd_addr addr;
+       char subaddr[16+1];
+       u_int8_t satype;
+       u_int8_t time;
+       int is_last;    
+} __attribute__ ((packed));
+
 #define GSMD_PIN_MAXLEN                8
 struct gsmd_pin {
        enum gsmd_pin_type type;

Modified: trunk/src/target/gsm/include/libgsmd/voicecall.h
===================================================================
--- trunk/src/target/gsm/include/libgsmd/voicecall.h    2008-01-02 08:37:09 UTC 
(rev 3759)
+++ trunk/src/target/gsm/include/libgsmd/voicecall.h    2008-01-03 09:13:39 UTC 
(rev 3760)
@@ -22,12 +22,28 @@
        LGSM_VOICECALL_CTRL_M_HELD                      = 6,    // 3
 };
 
+/* call forward reason from 3GPP TS 07.07 subclause 07.10 */
+enum lgsmd_voicecall_fwd_reason {
+       GSMD_VOICECALL_FWD_REASON_UNCOND                = 0,
+       GSMD_VOICECALL_FWD_REASON_BUSY                  = 1, 
+       GSMD_VOICECALL_FWD_REASON_NO_REPLY              = 2,
+       GSMD_VOICECALL_FWD_REASON_NOT_REACHABLE         = 3,
+       GSMD_VOICECALL_FWD_REASON_ALL_FORWARD           = 4,
+       GSMD_VOICECALL_FWD_REASON_ALL_COND_FORWARD      = 5, 
+};
+
 /* Refer to GSM 07.07 subclause 7.12 and 02.30 subclause 4.5.5.1 */
 struct lgsm_voicecall_ctrl {
        enum lgsm_voicecall_ctrl_proc proc;     
        int idx;
 };
 
+/* Refer to GSM 07.07 subclause 07.10 */
+struct lgsm_voicecall_fwd_reg {
+       enum lgsmd_voicecall_fwd_reason reason;
+       struct lgsm_addr number;        
+};
+
 /* Initiate an outgoing voice call */
 extern int lgsm_voice_out_init(struct lgsm_handle *lh, 
                               const struct lgsm_addr *number);
@@ -48,4 +64,23 @@
 extern int lgsm_voice_ctrl(struct lgsm_handle *lh, 
                               const struct lgsm_voicecall_ctrl *ctrl);
 
+/* disable call forwarding */
+extern int lgsm_voice_fwd_disable(struct lgsm_handle *lh, 
+                                 enum lgsmd_voicecall_fwd_reason reason);
+
+/* enable call forwarding */
+extern int lgsm_voice_fwd_enable(struct lgsm_handle *lh, 
+                                enum lgsmd_voicecall_fwd_reason reason);
+
+/* querty current status/setting of call forwarding */
+extern int lgsm_voice_fwd_stat(struct lgsm_handle *lh, 
+                              enum lgsmd_voicecall_fwd_reason reason);
+
+/* register call forwarding */
+extern int lgsm_voice_fwd_reg(struct lgsm_handle *lh, 
+                             struct lgsm_voicecall_fwd_reg *fwd_reg);
+
+/* erase the record of registered call forwarding */
+extern int lgsm_voice_fwd_erase(struct lgsm_handle *lh, 
+                               enum lgsmd_voicecall_fwd_reason reason);
 #endif

Modified: trunk/src/target/gsm/src/gsmd/usock.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/usock.c       2008-01-02 08:37:09 UTC (rev 
3759)
+++ trunk/src/target/gsm/src/gsmd/usock.c       2008-01-03 09:13:39 UTC (rev 
3760)
@@ -217,6 +217,75 @@
                        cmd->id, sizeof(ret), &ret);
 }
 
+static int voicecall_fwd_stat_cb(struct gsmd_atcmd *cmd, void *ctx, char 
*resp) 
+{
+       struct gsmd_user *gu = ctx;
+       struct gsm_extrsp *er;
+       struct gsmd_call_fwd_stat gcfs;
+       int ret = 0;
+       
+       DEBUGP("resp: %s\n", resp);
+       
+       er = extrsp_parse(cmd, resp);
+
+       if ( !er )
+               return -ENOMEM;
+
+       gcfs.is_last = (cmd->ret == 0 || cmd->ret == 4)? 1:0;
+
+       if ( er->num_tokens == 2 &&
+                       er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&
+                       er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC ) {
+
+               /*
+                * +CCFC: <status>,<class1>[,<number>,<type>
+                * [,<subaddr>,<satype>[,<time>]]][
+                * <CR><LF>+CCFC: <status>,<class2>[,<number>,<type>
+                * [,<subaddr>,<satype>[,<time>]]]
+                * [...]]
+                */
+
+               gcfs.status = er->tokens[0].u.numeric;
+               gcfs.classx = er->tokens[1].u.numeric;
+               gcfs.addr.number[0] = '\0';
+       }
+       else if ( er->num_tokens == 4 &&
+                       er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&
+                       er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC &&
+                       er->tokens[2].type == GSMD_ECMD_RTT_STRING &&
+                       er->tokens[3].type == GSMD_ECMD_RTT_NUMERIC ) {
+               
+               gcfs.status = er->tokens[0].u.numeric;
+               gcfs.classx = er->tokens[1].u.numeric;
+               strcpy(gcfs.addr.number, er->tokens[2].u.string);
+               gcfs.addr.type = er->tokens[3].u.numeric;
+       }
+       else if ( er->num_tokens == 7 &&
+                       er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&
+                       er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC &&
+                       er->tokens[2].type == GSMD_ECMD_RTT_STRING &&
+                       er->tokens[3].type == GSMD_ECMD_RTT_NUMERIC && 
+                       er->tokens[4].type == GSMD_ECMD_RTT_EMPTY &&
+                       er->tokens[5].type == GSMD_ECMD_RTT_EMPTY &&
+                       er->tokens[6].type == GSMD_ECMD_RTT_NUMERIC ) {
+               
+               gcfs.status = er->tokens[0].u.numeric;
+               gcfs.classx = er->tokens[1].u.numeric;
+               strcpy(gcfs.addr.number, er->tokens[2].u.string);
+               gcfs.addr.type = er->tokens[3].u.numeric;
+               gcfs.time = er->tokens[6].u.numeric;
+       }
+       else {
+               DEBUGP("Invalid Input : Parse error\n");
+               return -EINVAL;
+       }
+       
+       talloc_free(er);
+
+       return gsmd_ucmd_submit(gu, GSMD_MSG_VOICECALL, GSMD_VOICECALL_FWD_STAT,
+                       cmd->id, sizeof(gcfs), &gcfs);
+}
+
 static int usock_ringing_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
 {
         struct gsmd_user *gu = ctx;
@@ -235,7 +304,10 @@
        struct gsmd_addr *ga;
        struct gsmd_dtmf *gd;
        struct gsmd_call_ctrl *gcc; 
+       struct gsmd_call_fwd_reg *gcfr;
+       char buf[64];
        int atcmd_len;
+       int *reason;
                
        switch (gph->msg_subtype) {
        case GSMD_VOICECALL_DIAL:
@@ -329,7 +401,81 @@
                }
 
                break;
-       
+       case GSMD_VOICECALL_FWD_DIS:
+               if(len < sizeof(*gph) + sizeof(int))
+                       return -EINVAL;
+               
+               reason = (int *) ((void *)gph + sizeof(*gph));
+
+               sprintf(buf, "%d,0", *reason);
+
+               atcmd_len = 1 + strlen("AT+CCFC=") + strlen(buf);
+               cmd = atcmd_fill("AT+CCFC=", atcmd_len,
+                                &usock_cmd_cb, gu, gph->id, NULL);
+               if (!cmd)
+                       return -ENOMEM;
+               sprintf(cmd->buf, "AT+CCFC=%s", buf);
+               break;
+       case GSMD_VOICECALL_FWD_EN:
+               if(len < sizeof(*gph) + sizeof(int))
+                       return -EINVAL;
+               
+               reason = (int *) ((void *)gph + sizeof(*gph));
+
+               sprintf(buf, "%d,1", *reason);
+
+               atcmd_len = 1 + strlen("AT+CCFC=") + strlen(buf);
+               cmd = atcmd_fill("AT+CCFC=", atcmd_len,
+                                &usock_cmd_cb, gu, gph->id, NULL);
+               if (!cmd)
+                       return -ENOMEM;
+               sprintf(cmd->buf, "AT+CCFC=%s", buf);
+               break;
+       case GSMD_VOICECALL_FWD_STAT:
+               if(len < sizeof(*gph) + sizeof(int))
+                       return -EINVAL;
+               
+               reason = (int *) ((void *)gph + sizeof(*gph));
+
+               sprintf(buf, "%d,2", *reason);
+
+               atcmd_len = 1 + strlen("AT+CCFC=") + strlen(buf);
+               cmd = atcmd_fill("AT+CCFC=", atcmd_len,
+                                &voicecall_fwd_stat_cb, gu, gph->id, NULL);
+               if (!cmd)
+                       return -ENOMEM;
+               sprintf(cmd->buf, "AT+CCFC=%s", buf);
+               break;
+       case GSMD_VOICECALL_FWD_REG:
+               if(len < sizeof(*gph) + sizeof(int))
+                       return -EINVAL;
+               
+               gcfr = (struct gsmd_call_fwd_reg *) ((void *)gph + 
sizeof(*gph));
+
+               sprintf(buf, "%d,3,\"%s\"", gcfr->reason, gcfr->addr.number);
+
+               atcmd_len = 1 + strlen("AT+CCFC=") + strlen(buf);
+               cmd = atcmd_fill("AT+CCFC=", atcmd_len,
+                                &usock_cmd_cb, gu, gph->id, NULL);
+               if (!cmd)
+                       return -ENOMEM;
+               sprintf(cmd->buf, "AT+CCFC=%s", buf);
+               break;
+       case GSMD_VOICECALL_FWD_ERAS:
+               if(len < sizeof(*gph) + sizeof(int))
+                       return -EINVAL;
+               
+               reason = (int *) ((void *)gph + sizeof(*gph));
+
+               sprintf(buf, "%d,4", *reason);
+
+               atcmd_len = 1 + strlen("AT+CCFC=") + strlen(buf);
+               cmd = atcmd_fill("AT+CCFC=", atcmd_len,
+                                &usock_cmd_cb, gu, gph->id, NULL);
+               if (!cmd)
+                       return -ENOMEM;
+               sprintf(cmd->buf, "AT+CCFC=%s", buf);
+               break;
        default:
                return -EINVAL;
        }

Modified: trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c
===================================================================
--- trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c        2008-01-02 
08:37:09 UTC (rev 3759)
+++ trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c        2008-01-03 
09:13:39 UTC (rev 3760)
@@ -125,3 +125,126 @@
 
        return 0;
 }
+
+int lgsm_voice_fwd_disable(struct lgsm_handle *lh, 
+                          enum lgsmd_voicecall_fwd_reason reason)
+{
+       struct gsmd_msg_hdr *gmh;
+       int rc;
+
+       gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL,
+                       GSMD_VOICECALL_FWD_DIS, sizeof(int));
+       if (!gmh)
+               return -ENOMEM;
+
+       *(int *) gmh->data = reason;
+
+       rc = lgsm_send(lh, gmh);
+       if (rc < gmh->len + sizeof(*gmh)) {
+               lgsm_gmh_free(gmh);;
+               return -EIO;
+       }
+
+       lgsm_gmh_free(gmh);
+
+       return 0;
+}
+
+int lgsm_voice_fwd_enable(struct lgsm_handle *lh, 
+                          enum lgsmd_voicecall_fwd_reason reason)
+{
+       struct gsmd_msg_hdr *gmh;
+       int rc;
+
+       gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL,
+                       GSMD_VOICECALL_FWD_EN, sizeof(int));
+       if (!gmh)
+               return -ENOMEM;
+
+       *(int *) gmh->data = reason;
+
+       rc = lgsm_send(lh, gmh);
+       if (rc < gmh->len + sizeof(*gmh)) {
+               lgsm_gmh_free(gmh);;
+               return -EIO;
+       }
+
+       lgsm_gmh_free(gmh);
+
+       return 0;
+}
+
+int lgsm_voice_fwd_stat(struct lgsm_handle *lh, 
+                        enum lgsmd_voicecall_fwd_reason reason)
+{
+       struct gsmd_msg_hdr *gmh;
+       int rc;
+
+       gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL,
+                       GSMD_VOICECALL_FWD_STAT, sizeof(int));
+       if (!gmh)
+               return -ENOMEM;
+
+       *(int *) gmh->data = reason;
+
+       rc = lgsm_send(lh, gmh);
+       if (rc < gmh->len + sizeof(*gmh)) {
+               lgsm_gmh_free(gmh);;
+               return -EIO;
+       }
+
+       lgsm_gmh_free(gmh);
+
+       return 0;
+}
+
+int lgsm_voice_fwd_reg(struct lgsm_handle *lh, 
+                      struct lgsm_voicecall_fwd_reg *fwd_reg)
+{
+       struct gsmd_msg_hdr *gmh;
+       struct gsmd_call_fwd_reg *gcfr;
+       int rc;
+
+       gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL,
+                       GSMD_VOICECALL_FWD_REG, sizeof(struct 
gsmd_call_fwd_reg));
+       if (!gmh)
+               return -ENOMEM;
+
+       gcfr = (struct gsmd_call_fwd_reg *)gmh->data;
+       gcfr->reason = fwd_reg->reason;
+       strcpy(gcfr->addr.number, fwd_reg->number.addr);
+
+       rc = lgsm_send(lh, gmh);
+       if (rc < gmh->len + sizeof(*gmh)) {
+               lgsm_gmh_free(gmh);;
+               return -EIO;
+       }
+
+       lgsm_gmh_free(gmh);
+
+       return 0;
+}
+
+int lgsm_voice_fwd_erase(struct lgsm_handle *lh, 
+                         enum lgsmd_voicecall_fwd_reason reason)
+{
+       struct gsmd_msg_hdr *gmh;
+       int rc;
+
+       gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL,
+                       GSMD_VOICECALL_FWD_ERAS, sizeof(int));
+       if (!gmh)
+               return -ENOMEM;
+
+       *(int *) gmh->data = reason;
+
+       rc = lgsm_send(lh, gmh);
+       if (rc < gmh->len + sizeof(*gmh)) {
+               lgsm_gmh_free(gmh);;
+               return -EIO;
+       }
+
+       lgsm_gmh_free(gmh);
+
+       return 0;
+}

Modified: trunk/src/target/gsm/src/util/shell.c
===================================================================
--- trunk/src/target/gsm/src/util/shell.c       2008-01-02 08:37:09 UTC (rev 
3759)
+++ trunk/src/target/gsm/src/util/shell.c       2008-01-03 09:13:39 UTC (rev 
3760)
@@ -413,6 +413,7 @@
 static int call_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
 {
        struct gsmd_call_status *gcs;
+       struct gsmd_call_fwd_stat *gcfs;
        int *ret;
 
        switch (gmh->msg_subtype) {
@@ -440,6 +441,26 @@
                 (*ret)? printf("+CME ERROR %d\n", *ret) : printf("OK\n");
                pending_responses --;
                break;
+       case GSMD_VOICECALL_FWD_DIS:
+               pending_responses --;
+               break;
+       case GSMD_VOICECALL_FWD_EN:
+               pending_responses --;
+               break;
+       case GSMD_VOICECALL_FWD_STAT:
+               gcfs = (struct  gsmd_call_fwd_stat*) ((char *)gmh + 
sizeof(*gmh));
+               
+               printf("+CCFC:%d, %d, %s\n",gcfs->status, gcfs->classx, 
gcfs->addr.number);
+
+               if (gcfs->is_last)
+                       pending_responses --;
+               break;
+       case GSMD_VOICECALL_FWD_REG:
+               pending_responses --;
+               break;
+       case GSMD_VOICECALL_FWD_ERAS:
+               pending_responses --;
+               break;
        default:
                return -EINVAL;
        }
@@ -508,6 +529,11 @@
                "\tHa\tHold all active calls and accept held or waiting call 
(+CHLD=2)\n"
                "\tHx\tHold all active calls except call x (Hx=x)(+CHLD=2x)\n"
                "\tMP\tAdd a held call to the conversation (+CHLD=3)\n"
+               "\tCFD\tDisable call forwarding (CFD=reason)\n"
+               "\tCFE\tEnable call forwarding (CFE=reason)\n"
+               "\tCFQ\tQuery the status of call forwarding (CFQ=reason)\n"
+               "\tCFR\tRegister call forwarding (CFR=reason,number)\n"
+               "\tCFe\tErase a record of call forwarding (CFe=reason)\n"
                "\tq\tQuit\n"
                );
 }
@@ -862,7 +888,36 @@
                                printf("Add a held call to the conversation\n");
                                lgsm_voice_ctrl(lgsmh, &ctrl);
                                pending_responses ++;
-                       } else {
+                       } else if ( !strncmp(buf, "CFD", 3)) {
+                               printf("Disable call forwarding\n");
+                               ptr = strchr(buf, '=');
+                               lgsm_voice_fwd_disable(lgsmh, atoi(ptr+1));
+                               pending_responses ++;
+                       }else if ( !strncmp(buf, "CFE", 3)) {
+                               printf("Enable call forwarding\n");
+                               ptr = strchr(buf, '=');
+                               lgsm_voice_fwd_enable(lgsmh, atoi(ptr+1));
+                               pending_responses ++;
+                       }else if ( !strncmp(buf, "CFQ", 3)) {
+                               printf("Query the status of call forwarding\n");
+                               ptr = strchr(buf, '=');
+                               lgsm_voice_fwd_stat(lgsmh, atoi(ptr+1));
+                               pending_responses ++;
+                       }else if ( !strncmp(buf, "CFR", 3)) {
+                               struct lgsm_voicecall_fwd_reg lvfr;
+                               printf("Register call forwarding\n");
+                               ptr = strchr(buf, '=');
+                               lvfr.reason = atoi(ptr+1);
+                               ptr = strchr(buf, ',');
+                               strcpy(lvfr.number.addr, ptr+1);
+                               lgsm_voice_fwd_reg(lgsmh, &lvfr);
+                               pending_responses ++;
+                       }else if ( !strncmp(buf, "CFe", 3)) {
+                               printf("Erase a record of call forwarding\n");
+                               ptr = strchr(buf, '=');
+                               lgsm_voice_fwd_erase(lgsmh, atoi(ptr+1));
+                               pending_responses ++;
+                       }else {
                                printf("Unknown command `%s'\n", buf);
                        }
                }




--- End Message ---
_______________________________________________
commitlog mailing list
[email protected]
http://lists.openmoko.org/mailman/listinfo/commitlog

Reply via email to