1 /*
2
3 $Id$
4
5 G N O K I I
6
7 A Linux/Unix toolset and driver for the mobile phones.
8
9 This file is part of gnokii.
10
11 Gnokii is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 Gnokii is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with gnokii; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25 Copyright 2004 Hugo Haas <hugo@larve.net>
26 Copyright 2004-2008 Pawel Kot
27
28 This file provides functions specific to AT commands on Sony Ericsson
29 phones. See README for more details on supported mobile phones.
30
31 */
32
33 #include "config.h"
34
35 #include <string.h>
36 #include <stdlib.h>
37 #include <ctype.h>
38
39 #include "compat.h"
40 #include "misc.h"
41 #include "gnokii.h"
42 #include "phones/generic.h"
43 #include "phones/atgen.h"
44 #include "phones/atsoer.h"
45 #include "links/atbus.h"
46
se_at_memory_type_set(gn_memory_type mt,struct gn_statemachine * state)47 static gn_error se_at_memory_type_set(gn_memory_type mt, struct gn_statemachine *state)
48 {
49 at_driver_instance *drvinst = AT_DRVINST(state);
50 gn_data data;
51 char req[32];
52 const char *memory_name;
53 char memory_name_enc[16];
54 int len;
55 gn_error ret = GN_ERR_NONE;
56
57 if (mt != drvinst->memorytype) {
58 memory_name = gn_memory_type2str(mt);
59 if (!memory_name)
60 return GN_ERR_INVALIDMEMORYTYPE;
61 /* BC is "Own Business Card" as per the Sony Ericsson documentation */
62 if (strcmp(memory_name, "ON") == 0)
63 memory_name = "BC";
64 if (drvinst->encode_memory_type) {
65 gn_data_clear(&data);
66 at_encode(drvinst->charset, memory_name_enc, sizeof(memory_name_enc), memory_name, strlen(memory_name));
67 memory_name = memory_name_enc;
68 }
69 len = snprintf(req, sizeof(req), "AT+CPBS=\"%s\"\r", memory_name);
70 ret = sm_message_send(len, GN_OP_Init, req, state);
71 if (ret != GN_ERR_NONE)
72 return ret;
73 gn_data_clear(&data);
74 ret = sm_block_no_retry(GN_OP_Init, &data, state);
75 if (ret != GN_ERR_NONE)
76 return ret;
77 drvinst->memorytype = mt;
78
79 gn_data_clear(&data);
80 ret = state->driver.functions(GN_OP_AT_GetMemoryRange, &data, state);
81 }
82 return ret;
83 }
84
85 /*
86 * Calculate phonebook size for SonyEricsson phones: they don't respond
87 * with memory stats to AT+CPBS. Calculate by reading and counting all
88 * entries (which is fast -- just one command).
89 */
ReplyMemoryStatus(int messagetype,unsigned char * buffer,int length,gn_data * data,struct gn_statemachine * state)90 static gn_error ReplyMemoryStatus(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state)
91 {
92 at_driver_instance *drvinst = AT_DRVINST(state);
93 gn_error error;
94 char *buf = buffer;
95 int counter = 0;
96
97 if (!data->memory_status)
98 return GN_ERR_INTERNALERROR;
99
100 if ((error = at_error_get(buffer, state)) != GN_ERR_NONE)
101 return error;
102
103 while ((buf = strchr(buf, '\r'))) {
104 buf++;
105 if (strlen(buf) > 6 &&
106 (!strncmp(buf, "+CPBR:", 6) || !strncmp(buf + 1, "+CPBR:", 6)))
107 counter++;
108 }
109 data->memory_status->used += counter;
110 data->memory_status->free = drvinst->memorysize - data->memory_status->used;
111
112 return error;
113 }
114
115 /*
116 * Calculate phonebook size for SonyEricsson phones: they don't respond
117 * with memory stats to AT+CPBS. Calculate by reading and counting all
118 * entries (which is pretty fast).
119 */
120 #define PHONEBOOKREAD_CHUNK_SIZE 200
AT_GetMemoryStatus(gn_data * data,struct gn_statemachine * state)121 static gn_error AT_GetMemoryStatus(gn_data *data, struct gn_statemachine *state)
122 {
123 at_driver_instance *drvinst = AT_DRVINST(state);
124 gn_error ret = GN_ERR_NONE;
125 char req[32];
126 int top, bottom;
127
128 ret = se_at_memory_type_set(data->memory_status->memory_type, state);
129 if (ret)
130 return ret;
131 ret = state->driver.functions(GN_OP_AT_GetMemoryRange, data, state);
132 if (ret)
133 return ret;
134 data->memory_status->used = 0;
135 bottom = 0;
136 at_set_charset(data, state, AT_CHAR_UCS2);
137 top = (bottom + PHONEBOOKREAD_CHUNK_SIZE > drvinst->memorysize) ? drvinst->memorysize : bottom + PHONEBOOKREAD_CHUNK_SIZE;
138 while (top <= drvinst->memorysize) {
139 snprintf(req, sizeof(req) - 1, "AT+CPBR=%d,%d\r", drvinst->memoryoffset + 1 + bottom, top + drvinst->memoryoffset);
140 ret = sm_message_send(strlen(req), GN_OP_GetMemoryStatus, req, state);
141 if (ret)
142 return GN_ERR_NOTREADY;
143 ret = sm_block_no_retry(GN_OP_GetMemoryStatus, data, state);
144 if (ret)
145 return ret;
146
147 bottom = top;
148 top = bottom + PHONEBOOKREAD_CHUNK_SIZE;
149 if (bottom >= drvinst->memorysize)
150 break;
151 if (top > drvinst->memorysize)
152 top = drvinst->memorysize;
153 }
154 dprintf("Got %d entries\n", data->memory_status->used);
155
156 return ret;
157 }
158
at_sonyericsson_init(char * foundmodel,char * setupmodel,struct gn_statemachine * state)159 void at_sonyericsson_init(char* foundmodel, char* setupmodel, struct gn_statemachine *state)
160 {
161 /* Sony Ericssons support just mode 2 */
162 AT_DRVINST(state)->cnmi_mode = 2;
163 AT_DRVINST(state)->encode_memory_type = 1;
164 AT_DRVINST(state)->encode_number = 1;
165 AT_DRVINST(state)->lac_swapped = 1;
166
167 /*
168 * Calculate phonebook size for SonyEricsson phones: they don't respond
169 * with memory stats to AT+CPBS. Calculate by reading and counting all
170 * entries (which is fast -- just one command).
171 */
172 at_insert_send_function(GN_OP_GetMemoryStatus, AT_GetMemoryStatus, state);
173 at_insert_recv_function(GN_OP_GetMemoryStatus, ReplyMemoryStatus, state);
174 }
175