| @@ -0,0 +1,217 @@ |
| | 1 | /* TODO/BUGS in no order: |
| | 2 | should send acknowledgement when an sms is read from /phone/sms, not just on every read |
| | 3 | consider notifying RIL of screen state using RIL_REQUEST_SCREEN_STATE to conserve power |
| | 4 | too many assumptions made in loop_for_data() about read() giving exactly the right amount of data |
| | 5 | parcel code will go crazy if ints overflow |
| | 6 | need to support DTMF |
| | 7 | */ |
| | 8 | |
| | 9 | #include "dat.h" |
| | 10 | #include "fns.h" |
| | 11 | #include "error.h" |
| | 12 | #include "version.h" |
| | 13 | #include "mp.h" |
| | 14 | #include "libsec.h" |
| | 15 | #include "keyboard.h" |
| | 16 | #include <stdio.h> |
| | 17 | #include <cutils/sockets.h> |
| | 18 | #include <stdlib.h> |
| | 19 | #include <cutils/jstring.h> |
| | 20 | #include <arpa/inet.h> |
| | 21 | #include <libgen.h> |
| | 22 | #include <sys/types.h> |
| | 23 | #include <sys/stat.h> |
| | 24 | #include <fcntl.h> |
| | 25 | #include <dlfcn.h> |
| | 26 | |
| | 27 | // Inferno-related globals |
| | 28 | |
| | 29 | enum |
| | 30 | { |
| | 31 | Qdir, |
| | 32 | Qctl |
| | 33 | }; |
| | 34 | |
| | 35 | Dirtab wifitab[] = |
| | 36 | { |
| | 37 | ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, |
| | 38 | "wifictl", {Qctl}, 0, 0666, |
| | 39 | }; |
| | 40 | |
| | 41 | static struct { |
| | 42 | QLock l; |
| | 43 | Rendez r; |
| | 44 | int ready; |
| | 45 | int used; |
| | 46 | char *msg; |
| | 47 | } status_msg; |
| | 48 | |
| | 49 | #define DPRINT if(1) print |
| | 50 | |
| | 51 | void |
| | 52 | wifiinit(void) |
| | 53 | { |
| | 54 | int pid; |
| | 55 | |
| | 56 | pid = fork(); |
| | 57 | |
| | 58 | if (pid == 0) { |
| | 59 | chdir("/data/misc/wifi"); |
| | 60 | execl("/system/bin/wpa_supplicant", "wpa_supplicant", "-D", "wext", "-i", "eth0", "-c", "/data/misc/wifi/wpa_supplicant.conf", NULL); |
| | 61 | } |
| | 62 | // kproc("phone", loop_for_data, 0, 0); |
| | 63 | } |
| | 64 | |
| | 65 | static Chan* |
| | 66 | wifiattach(char *spec) |
| | 67 | { |
| | 68 | // setup kprocs if necessary |
| | 69 | return devattach('w', spec); |
| | 70 | } |
| | 71 | |
| | 72 | static Walkqid* |
| | 73 | wifiwalk(Chan *c, Chan *nc, char **name, int nname) |
| | 74 | { |
| | 75 | return devwalk(c, nc, name, nname, wifitab, nelem(wifitab), devgen); |
| | 76 | } |
| | 77 | |
| | 78 | static int |
| | 79 | wifistat(Chan *c, uchar *db, int n) |
| | 80 | { |
| | 81 | return devstat(c, db, n, wifitab, nelem(wifitab), devgen); |
| | 82 | } |
| | 83 | |
| | 84 | static Chan* |
| | 85 | wifiopen(Chan *c, int omode) |
| | 86 | { |
| | 87 | c = devopen(c, omode, wifitab, nelem(wifitab), devgen); |
| | 88 | |
| | 89 | return c; |
| | 90 | } |
| | 91 | |
| | 92 | static void |
| | 93 | wificlose(Chan *c) |
| | 94 | { |
| | 95 | if((c->flag & COPEN) == 0) |
| | 96 | return; |
| | 97 | } |
| | 98 | |
| | 99 | static long |
| | 100 | wifiread(Chan *c, void *va, long n, vlong offset) |
| | 101 | { |
| | 102 | char buf[255]; |
| | 103 | int i, str_offset; |
| | 104 | if(c->qid.type & QTDIR) { |
| | 105 | return devdirread(c, va, n, wifitab, nelem(wifitab), devgen); |
| | 106 | } |
| | 107 | |
| | 108 | switch((ulong) c->qid.path) { |
| | 109 | case Qctl: |
| | 110 | // return readstr(offset, va, n, power_state ? "on\n" : "off\n"); |
| | 111 | return 0; |
| | 112 | } |
| | 113 | return 0; |
| | 114 | } |
| | 115 | |
| | 116 | static long |
| | 117 | wifiwrite(Chan *c, void *va, long n, vlong offset) |
| | 118 | { |
| | 119 | char *pdu; |
| | 120 | Rune *runestr; |
| | 121 | int i, j; |
| | 122 | Cmdbuf *cmd; |
| | 123 | |
| | 124 | if(c->qid.type & QTDIR) |
| | 125 | error(Eperm); |
| | 126 | |
| | 127 | cmd = parsecmd(va, n); |
| | 128 | if(waserror()) { |
| | 129 | free(cmd); |
| | 130 | nexterror(); |
| | 131 | return 0; |
| | 132 | } |
| | 133 | |
| | 134 | switch((ulong) c->qid.path) { |
| | 135 | case Qctl: |
| | 136 | // Here we just look for which commands were sent. The nesting |
| | 137 | // can get pretty ugly for commands with a lot of parameters |
| | 138 | // (sorry!) |
| | 139 | // if(strcmp(cmd->f[0], "on") == 0) { |
| | 140 | // radio_power(1); |
| | 141 | // } else if(strcmp(cmd->f[0], "off") == 0) { |
| | 142 | // radio_power(0); |
| | 143 | // } else if(strcmp(cmd->f[0], "net") == 0) { |
| | 144 | // if(cmd->nf >= 2) { |
| | 145 | // if(strcmp(cmd->f[1], "on") == 0) { |
| | 146 | // // Ugly to do a different thing for each |
| | 147 | // // # of parameters, but cmd->f is |
| | 148 | // // dynamically allocated so we can't |
| | 149 | // // just set cmd->f[cmd-nf:end] to NULL |
| | 150 | // switch(cmd->nf) { |
| | 151 | // case 2: activate_net(NULL, NULL, NULL, NULL); |
| | 152 | // break; |
| | 153 | // case 3: activate_net(cmd->f[2], NULL, NULL, NULL); |
| | 154 | // break; |
| | 155 | // case 4: activate_net(cmd->f[2], cmd->f[3], NULL, NULL); |
| | 156 | // break; |
| | 157 | // case 5: activate_net(cmd->f[2], cmd->f[3], cmd->f[4], NULL); |
| | 158 | // break; |
| | 159 | // default: activate_net(cmd->f[2], cmd->f[3], cmd->f[4], cmd->f[5]); |
| | 160 | // break; |
| | 161 | // } |
| | 162 | // } else if(strcmp(cmd->f[1], "off") == 0) { |
| | 163 | // deactivate_net(); |
| | 164 | // } |
| | 165 | // } |
| | 166 | // } else if(strcmp(cmd->f[0], "mute") == 0) { |
| | 167 | // set_mute(1); |
| | 168 | // } else if(strcmp(cmd->f[0], "unmute") == 0) { |
| | 169 | // set_mute(0); |
| | 170 | // } else if(strcmp(cmd->f[0], "route") == 0) { |
| | 171 | // if(cmd->nf >= 2) { |
| | 172 | // if(strcmp(cmd->f[1], "earpiece") == 0) { |
| | 173 | // af_setParameters("routing=1"); |
| | 174 | // } else if(strcmp(cmd->f[1], "speaker") == 0) { |
| | 175 | // af_setParameters("routing=2"); |
| | 176 | // } else if(strcmp(cmd->f[1], "headphone") == 0) { |
| | 177 | // af_setParameters("routing=3"); |
| | 178 | // } |
| | 179 | // } |
| | 180 | // } else if(strcmp(cmd->f[0], "volume") == 0) { |
| | 181 | // if(cmd->nf >= 2) { |
| | 182 | // switch(strtol(cmd->f[1], NULL, 10)) { |
| | 183 | // case 0: af_setVoiceVolume(0.0); break; |
| | 184 | // case 1: af_setVoiceVolume(0.2); break; |
| | 185 | // case 2: af_setVoiceVolume(0.4); break; |
| | 186 | // case 3: af_setVoiceVolume(0.6); break; |
| | 187 | // case 4: af_setVoiceVolume(0.8); break; |
| | 188 | // case 5: af_setVoiceVolume(1.0); break; |
| | 189 | // default: af_setVoiceVolume(1.0); break; |
| | 190 | // } |
| | 191 | // } |
| | 192 | // } |
| | 193 | break; |
| | 194 | } |
| | 195 | poperror(); |
| | 196 | free(cmd); |
| | 197 | return n; |
| | 198 | } |
| | 199 | |
| | 200 | Dev wifidevtab = { |
| | 201 | 'w', |
| | 202 | "wifi", |
| | 203 | |
| | 204 | wifiinit, |
| | 205 | wifiattach, |
| | 206 | wifiwalk, |
| | 207 | wifistat, |
| | 208 | wifiopen, |
| | 209 | devcreate, |
| | 210 | wificlose, |
| | 211 | wifiread, |
| | 212 | devbread, |
| | 213 | wifiwrite, |
| | 214 | devbwrite, |
| | 215 | devremove, |
| | 216 | devwstat |
| | 217 | }; |