--- common/phones/atgen.c~ 2004-03-16 23:47:48.000000000 +0100 +++ common/phones/atgen.c 2004-03-16 23:52:14.000000000 +0100 @@ -320,22 +320,120 @@ drvinst->charset = AT_CHAR_UNKNOWN; } +static char *charset2string(at_charset charset) +{ + switch (charset) { + case AT_CHAR_GSM: + return "GSM"; + break; + case AT_CHAR_CP437: + return "PCCP437"; + break; + case AT_CHAR_HEXGSM: + return "HEX"; + break; + case AT_CHAR_HEX437: + return "HEX437"; + break; + case AT_CHAR_UCS2: + return "UCS2"; + break; + default: + return "UNKNOWN"; + break; + } +} + +/* Try to set a given charset */ +static gn_error AT_TryCharset(gn_data *data, struct gn_statemachine *state) +{ + at_driver_instance *drvinst = AT_DRVINST(state); + gn_data tmpdata; + char req[64]; + gn_error error; + + /* check available charsets */ + error = sm_message_send(10, GN_OP_AT_GetCharset, "AT+CSCS=?\r", state); + if (error) + return error; + gn_data_clear(&tmpdata); + error = sm_block_no_retry(GN_OP_AT_GetCharset, &tmpdata, state); + if (!error) + if (drvinst->availcharsets & drvinst->charset) { + /* Required charset found. try to set it */ + memset(req, 0, sizeof(req)); + sprintf(req, "AT+CSCS=\"%s\"\r", charset2string(drvinst->charset)); + error = sm_message_send(15, GN_OP_Init, req, state); + if (error) + return error; + error = sm_block_no_retry(GN_OP_Init, &tmpdata, state); + } else { + error = GN_ERR_NOTSUPPORTED; + } + return error; +} + +/* This function has side effect: may change the used charset + * TODO: add an argument that allows to avoid charset change + */ gn_error at_memory_type_set(gn_memory_type mt, struct gn_statemachine *state) { at_driver_instance *drvinst = AT_DRVINST(state); gn_data data; char req[32]; gn_error ret = GN_ERR_NONE; + int tryagain, succeeded; + tryagain = succeeded = 0; + /* Quoting Hugo Haas email to gnokii-ml: + * "I investigated further the issues with my T610, and realized that + * things go wrong once the character encoding is set to UCS2. As an + * example with minicom: + * + * ATZ + * OK + * AT+CPBS="ME" + * OK + * AT+CSCS="UCS2" + * OK + * AT+CPBS="ME" + * ERROR + * " + * We'll try to solve this falling back to GSM charset when we got + * the error. I hope nothing depends here on charset. If it does: FIXME + */ if (mt != drvinst->memorytype) { - sprintf(req, "AT+CPBS=\"%s\"\r", memorynames[mt]); - ret = sm_message_send(13, GN_OP_Init, req, state); - if (ret) - return GN_ERR_NOTREADY; - gn_data_clear(&data); - ret = sm_block_no_retry(GN_OP_Init, &data, state); - if (ret == GN_ERR_NONE) - drvinst->memorytype = mt; + do { + sprintf(req, "AT+CPBS=\"%s\"\r", memorynames[mt]); + ret = sm_message_send(13, GN_OP_Init, req, state); + if (ret) + return GN_ERR_NOTREADY; + gn_data_clear(&data); + ret = sm_block_no_retry(GN_OP_Init, &data, state); + if (ret == GN_ERR_NONE) { + drvinst->memorytype = mt; + succeeded = 1; + tryagain = 0; + } else { + at_charset charset; + gn_error error; + + if (!tryagain) { + /* Fallback to GSM charset */ + charset = drvinst->charset; + drvinst->charset = AT_CHAR_GSM; + error = AT_TryCharset(&data, state); + if (error != GN_ERR_NONE) { + /* Giveup */ + drvinst->charset = charset; + return ret; + } + tryagain = 1; + } else { + tryagain = 0; + } + } + } while (!succeeded || tryagain); gn_data_clear(&data); ret = state->driver.functions(GN_OP_AT_GetMemoryRange, &data, state); @@ -365,28 +463,29 @@ /* AT_SetCharset * - * before we start sending or receiving phonebook entries from the phone, - * we should set a charset. this is done once before the first read or write. + * Before we start sending or receiving phonebook entries from the phone, + * we should set a charset. This is done once before the first read or write. * - * we try to chose a charset with hexadecimal representation. first ucs2 + * We try to chose a charset with hexadecimal representation. First ucs2 * (which is a hexencoded unicode charset) is tested and set if available. - * if this fails for any reason, it is checked if the original charset is - * GSM. if this is true, we try to set HEX (a hexencoded GSM charset). if - * this again fails or is impossible, we try to use the GSM charset. if + * If this fails for any reason, it is checked if the original charset is + * GSM. If this is true, we try to set HEX (a hexencoded GSM charset). If + * this again fails or is impossible, we try to use the GSM charset. If * the original charset was GSM nothing is done (we rely on not changing - * anything by the failing tries before). if the original charset was - * something else, we set the GSM charset. if this too fails, the user is + * anything by the failing tries before). If the original charset was + * something else, we set the GSM charset. If this too fails, the user is * on his own, characters will be copied from or to the phone without * conversion. * - * the whole bunch is needed to get a reasonable support for different - * phones. eg a siemens s25 has GSM as original charset and aditional + * The whole bunch is needed to get a reasonable support for different + * phones. Eg a siemens s25 has GSM as original charset and aditional * supports only UCS2, a nokia 7110 has PCCP437 as original charset which * renders HEX unusable for us (in this case HEX will give a hexadecimal - * encoding of the PCCP437 charset) and no UCS2. a ericsson t39 uses + * encoding of the PCCP437 charset) and no UCS2. An ericsson t39 uses * GSM as original charset but has never heard of any hex encoded charset. * but this doesn't matter with IRDA and i haven't found a serial cable - * in a shop yet, so this is no problem + * in a shop yet, so this is no problem. Nokia 6310 reports: UCS2, GSM, + * PCCP437, PCDN, IRA, 8859-1 and HEX as available. * * see AT_GetCharset, StoreDefaultCharset */