This source file includes following definitions.
- clear_eyefi_buf
- atoh
- convert_ascii_to_hex
- hex_only
- make_network_key
- eyefi_filename
- eyefi_writeFile
- eyefi_readFile
- eyefi_sendCommandParam
- eyefi_networkAction
- eyefi_deleteNetwork
- eyefi_testNetwork
- eyefi_addNetwork
- eyefi_enableWlan
- eyefi_statusName
- eyefi_exit
- eyefi_wlan_state
- confirm_delete_network_cb
- select_configured_network_cb
- eyefi_configured_networks
- confirm_add_network_cb
- password_cb
- select_available_network_cb
- eyefi_available_networks
- eyefi_wlan_off
- eyefi_wlan_on
- _module_can_unload
- _run
- _module_exit_alt
1
2
3
4
5
6
7
8 #include "gui.h"
9 #include "string.h"
10 #include "ctype.h"
11 #include "gui_lang.h"
12 #include "gui_mbox.h"
13 #include "gui_tbox.h"
14 #include "gui_mpopup.h"
15 #include "gui_menu.h"
16 #include "eyefi.h"
17
18
19
20 #define EINVAL 1000
21 #define EYEFI_BUF_SIZE 16384
22 #define ESSID_LEN 32
23
24
25 #define WPA_KEY_BYTES 32
26 #define WEP_KEY_BYTES 13
27 #define WEP_40_KEY_BYTES 5
28
29
30 enum test_status
31 {
32 EYEFI_NOT_SCANNING,
33 EYEFI_LOCATING_NETWORK,
34 EYEFI_VERIFYING_NETWORK_KEY,
35 EYEFI_WAITING_FOR_DHCP,
36 EYEFI_TESTING_CONN_TO_SERVER,
37 EYEFI_SUCCESS
38 };
39
40
41
42
43 enum card_info_subcommand
44 {
45 EYEFI_MAC_ADDRESS = 1,
46 EYEFI_FIRMWARE_INFO = 2,
47 EYEFI_CARD_KEY = 3,
48 EYEFI_API_URL = 4,
49 EYEFI_UNKNOWN_5 = 5,
50 EYEFI_UNKNOWN_6 = 6,
51 EYEFI_LOG_LEN = 7,
52 EYEFI_WLAN_DISABLE = 10,
53 EYEFI_UPLOAD_PENDING= 11,
54 EYEFI_HOTSPOT_ENABLE= 12,
55 EYEFI_CONNECTED_TO = 13,
56 EYEFI_UPLOAD_STATUS = 14,
57 EYEFI_UNKNOWN_15 = 15,
58 EYEFI_TRANSFER_MODE = 17,
59 EYEFI_ENDLESS = 27,
60 EYEFI_DIRECT_WAIT_FOR_CONNECTION = 0x24,
61 EYEFI_DIRECT_WAIT_AFTER_TRANSFER = 0x25,
62 EYEFI_UNKNOWN_ff = 0xff,
63
64
65
66
67
68
69 };
70
71
72 struct network_key
73 {
74 u8 len;
75 u8 key[WPA_KEY_BYTES];
76 } __attribute__((packed));
77
78
79
80
81 typedef struct
82 {
83 char essid[ESSID_LEN];
84 signed char strength;
85 u8 type;
86 } __attribute__((packed)) scanned_net;
87
88
89 typedef struct
90 {
91 char essid[ESSID_LEN];
92 } __attribute__((packed)) configured_net;
93
94
95 typedef struct
96 {
97 u8 count;
98 scanned_net nets[32];
99 } __attribute__((packed)) scanned_nets;
100
101
102 typedef struct
103 {
104 u8 count;
105 configured_net nets[32];
106 } __attribute__((packed)) configured_nets;
107
108
109 typedef struct
110 {
111 union {
112 struct {
113 unsigned char subcommand;
114 unsigned char bytes;
115 unsigned char args[32];
116 } __attribute__((packed)) config;
117 struct {
118 unsigned char length;
119 char SSID[32];
120 struct network_key key;
121 } __attribute__((packed)) network;
122 };
123 } __attribute__((packed)) eyefi_param;
124
125
126 typedef struct
127 {
128 u8 cmd;
129 eyefi_param param;
130 } __attribute__((packed)) eyefi_command;
131
132
133
134
135 typedef struct
136 {
137 union
138 {
139 u8 status;
140 unsigned int seq;
141 scanned_nets a;
142 configured_nets c;
143 eyefi_command ec;
144 unsigned char buf[EYEFI_BUF_SIZE];
145 };
146 } __attribute__((packed)) _eyefi_interface;
147
148 static int running = 0;
149 static _eyefi_interface eyefi_buf;
150
151 static void clear_eyefi_buf()
152 {
153 memset(eyefi_buf.buf, 0, EYEFI_BUF_SIZE);
154 }
155
156 static u8 atoh(char c)
157 {
158 char lc = tolower(c);
159 if ((c >= '0') && (c <= '9'))
160 return c - '0';
161 else if ((lc >= 'a') && (lc <= 'z'))
162 return (lc - 'a') + 10;
163 return 0;
164 }
165
166
167
168
169
170
171
172 static u8 *convert_ascii_to_hex(char *ascii)
173 {
174 int i;
175 static u8 hex[32];
176 int len = strlen(ascii);
177
178 memset(hex, 0, 32);
179
180 for (i = 0; i < len; i += 2)
181 {
182 u8 high = atoh(ascii[i]);
183 u8 low = atoh(ascii[i+1]);
184 hex[i/2] = (high<<4) | low;
185 }
186
187 return hex;
188 }
189
190 static int hex_only(char *str)
191 {
192 int i;
193
194 for (i = 0; i < strlen(str); i++) {
195 if (((str[i] >= 'a') && str[i] <= 'f') ||
196 ((str[i] >= 'A') && str[i] <= 'F') ||
197 ((str[i] >= '0') && str[i] <= '9')) {
198 continue;
199 }
200 return 0;
201 }
202 return 1;
203 }
204
205
206
207 static int make_network_key(struct network_key *key, char *essid, char *pass)
208 {
209 u8 *hex_pass;
210 int pass_len = strlen(pass);
211 memset(key, 0, sizeof(*key));
212
213 switch (pass_len) {
214 case WPA_KEY_BYTES*2:
215 case WEP_KEY_BYTES*2:
216 case WEP_40_KEY_BYTES*2:
217 if (hex_only(pass))
218 {
219 hex_pass = convert_ascii_to_hex(pass);
220 if (!hex_pass)
221 return -EINVAL;
222 key->len = pass_len/2;
223 memcpy(&key->key[0], hex_pass, key->len);
224 break;
225 }
226
227 default:
228 key->len = WPA_KEY_BYTES;
229 pbkdf2_sha1(pass, essid, strlen(essid), 4096, &key->key[0], WPA_KEY_BYTES);
230 break;
231 }
232 return 0;
233 }
234
235
236 static char *eyefi_filename(const char *nm)
237 {
238 static char path[16];
239
240 strcpy(path, "A/EyeFi/");
241 strcat(path, nm);
242
243 return path;
244 }
245
246
247
248 static int eyefi_writeFile(const char *filename)
249 {
250 int fd = open(eyefi_filename(filename), O_RDWR|O_CREAT, 0600);
251
252 if (fd < 0)
253 return 0;
254
255 int bytesWritten = write(fd, eyefi_buf.buf, EYEFI_BUF_SIZE);
256 close(fd);
257
258 return bytesWritten == EYEFI_BUF_SIZE;
259 }
260
261
262
263 static int eyefi_readFile(const char *filename)
264 {
265 clear_eyefi_buf();
266
267 int fd = open(eyefi_filename(filename), O_RDONLY, 0777);
268
269 if (fd < 0)
270 return 0;
271
272 int bytesRead = read(fd, eyefi_buf.buf, EYEFI_BUF_SIZE);
273 close(fd);
274
275 return bytesRead == EYEFI_BUF_SIZE;
276 }
277
278
279
280
281
282
283
284
285 static int eyefi_sendCommandParam(unsigned char cmd, eyefi_param *param)
286 {
287 int i;
288
289 if (!eyefi_readFile("RSPC")) return 0;
290 unsigned int cur_seq = eyefi_buf.seq;
291
292 clear_eyefi_buf();
293 eyefi_buf.ec.cmd = cmd;
294
295 if (param)
296 memcpy(&eyefi_buf.ec.param, param, sizeof(eyefi_param));
297
298 if (!eyefi_writeFile("REQM")) return -1;
299
300 clear_eyefi_buf();
301 eyefi_buf.seq = ++cur_seq;
302 if (!eyefi_writeFile("REQC")) return -2;
303
304 for (i=0; i<20; i++)
305 {
306 if (!eyefi_readFile("RSPC")) return -3;
307 if (eyefi_buf.seq == cur_seq)
308 {
309 if (!eyefi_readFile("RSPM")) return -5;
310 return 1;
311 }
312 msleep(250);
313 }
314
315 return -4;
316 }
317
318 #define eyefi_sendCommand(cmd) eyefi_sendCommandParam(cmd, NULL)
319 #define eyefi_getAvailableNetworks() eyefi_sendCommand('g')
320 #define eyefi_getConfiguredNetworks() eyefi_sendCommand('l')
321 #define eyefi_getNetworkStatus() eyefi_sendCommand('s')
322
323
324 int eyefi_networkAction(unsigned char cmd, char *SSID, char *pwd)
325 {
326 eyefi_param param;
327 memset(¶m, 0, sizeof(eyefi_param));
328 param.network.length = (unsigned char)strlen(SSID);
329 strcpy(param.network.SSID, SSID);
330 if (pwd)
331 {
332 make_network_key(¶m.network.key, SSID, pwd);
333 }
334 return eyefi_sendCommandParam(cmd, ¶m);
335 }
336
337 int eyefi_deleteNetwork(char *SSID)
338 {
339 return eyefi_networkAction('d', SSID, NULL);
340 }
341
342 int eyefi_testNetwork(char *SSID,char *pwd)
343 {
344 return eyefi_networkAction('t', SSID, pwd);
345 }
346
347 int eyefi_addNetwork(char *SSID,char *pwd)
348 {
349 return eyefi_networkAction('a', SSID, pwd);
350 }
351
352
353 int eyefi_enableWlan(int enable)
354 {
355 eyefi_param param;
356 memset(¶m, 0, sizeof(eyefi_param));
357 param.config.subcommand = EYEFI_WLAN_DISABLE;
358 param.config.bytes = 1;
359 param.config.args[0] = (unsigned char)enable;
360 return eyefi_sendCommandParam('O', ¶m);
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374 char *eyefi_statusName(int n)
375 {
376 static char *eyefi_status[] =
377 {
378 "not scanning",
379 "locating network",
380 "verifying network_key",
381 "waiting for DHCP",
382 "testing conn. to server",
383 "success"
384 };
385
386 if (n<0 || n>=(int)(sizeof(eyefi_status)/sizeof(*eyefi_status)))
387 return "?";
388
389 return eyefi_status[n];
390 }
391
392
393
394
395 #define MAX_NETWORK 9
396 #define PWD_LEN 32
397
398 static struct mpopup_item popup_eyefi[MAX_NETWORK+1];
399 static char eyefi_selectedNetwork[ESSID_LEN+1];
400 static char eyefi_password[PWD_LEN+1];
401
402
403 static void eyefi_exit(__attribute__ ((unused))unsigned int button)
404 {
405 running = 0;
406 gui_set_need_restore();
407 }
408
409 static void eyefi_wlan_state(int on_off)
410 {
411 running = 1;
412
413 int n = eyefi_enableWlan(on_off);
414
415 if (n <= 0)
416 gui_mbox_init(LANG_ERROR_INITIALIZING_EYEFI,LANG_NO_EYEFI_CARD_FOUND,MBOX_BTN_OK,eyefi_exit);
417 else
418 gui_mbox_init(LANG_SUCCESS,(on_off)?LANG_EYEFI_WLAN_TURNED_ON:LANG_EYEFI_WLAN_TURNED_OFF,MBOX_BTN_OK,eyefi_exit);
419 }
420
421 static void confirm_delete_network_cb(unsigned int btn)
422 {
423 if (btn == MBOX_BTN_YES)
424 {
425 int n = eyefi_deleteNetwork(eyefi_selectedNetwork);
426 gui_mbox_init(LANG_SUCCESS,n<=0?LANG_CANNOT_DELETE_NETWORK:LANG_NETWORK_DELETED,MBOX_BTN_OK,eyefi_exit);
427 }
428 eyefi_exit(0);
429 }
430
431 static void select_configured_network_cb(unsigned nSelected)
432 {
433 unsigned flag=1;
434 int i, n;
435
436 if (nSelected == MPOPUP_CANCEL)
437 {
438 eyefi_exit(0);
439 return;
440 }
441
442 n = eyefi_buf.c.count;
443 for (i=0; i<n && i<MAX_NETWORK; i++)
444 {
445 if (nSelected == flag) break;
446 flag <<= 1;
447 }
448
449 if (nSelected != flag)
450 {
451 gui_mbox_init(LANG_POPUP_DELETE,LANG_CANNOT_FIND_NETWORK,MBOX_BTN_OK,eyefi_exit);
452 return;
453 }
454
455 strcpy(eyefi_selectedNetwork, eyefi_buf.c.nets[i].essid);
456
457 static char s[80];
458 sprintf(s,"Delete \"%s\"?",eyefi_selectedNetwork);
459 gui_mbox_init(LANG_POPUP_DELETE,(int)s,MBOX_BTN_YES_NO|MBOX_DEF_BTN2,confirm_delete_network_cb);
460 }
461
462 static void eyefi_configured_networks()
463 {
464 unsigned flag=1,flags=0;
465 int i,n;
466
467 running = 1;
468
469 if (eyefi_getConfiguredNetworks() <= 0)
470 {
471 gui_mbox_init(LANG_ERROR_INITIALIZING_EYEFI,LANG_NO_EYEFI_CARD_FOUND,MBOX_BTN_OK,eyefi_exit);
472 }
473 else
474 {
475 memset(eyefi_selectedNetwork, 0, sizeof(eyefi_selectedNetwork));
476 n = eyefi_buf.c.count;
477 for (i=0; i<n && i<MAX_NETWORK; i++)
478 {
479 popup_eyefi[i].text = (int)(eyefi_buf.c.nets[i].essid);
480 popup_eyefi[i].flag = flag;
481 flags |= flag;
482 flag <<= 1;
483 }
484 popup_eyefi[i].text = (int)"Cancel";
485 popup_eyefi[i].flag = MPOPUP_CANCEL;
486
487 libmpopup->show_popup(popup_eyefi, flags, select_configured_network_cb);
488 }
489 }
490
491 static void confirm_add_network_cb(unsigned int btn)
492 {
493 int n,i;
494
495 if (btn==MBOX_BTN_YES)
496 {
497 n = eyefi_testNetwork(eyefi_selectedNetwork, eyefi_password);
498 gui_browser_progress_show("testing network",5);
499 for (i=0; i<50; i++)
500 {
501 msleep(10);
502 n = eyefi_getNetworkStatus();
503 if (eyefi_buf.status == 0)
504 {
505 gui_mbox_init(LANG_FAILED,LANG_WRONG_PASSWORD,MBOX_BTN_OK,eyefi_exit);
506 return;
507 }
508 if (eyefi_buf.status <= EYEFI_SUCCESS)
509 {
510 gui_browser_progress_show(eyefi_statusName(eyefi_buf.status),(eyefi_buf.status*100)/(EYEFI_SUCCESS+1));
511 if (eyefi_buf.status == EYEFI_SUCCESS)
512 break;
513 }
514 else
515 gui_browser_progress_show("????",50);
516 }
517
518 if (eyefi_buf.status != EYEFI_SUCCESS)
519 {
520 gui_mbox_init(LANG_FAILED,LANG_WRONG_PASSWORD,MBOX_BTN_OK,eyefi_exit);
521 return;
522 }
523 }
524
525 gui_browser_progress_show("adding network", 95);
526 n = eyefi_addNetwork(eyefi_selectedNetwork, eyefi_password);
527 if (n > 0)
528 gui_mbox_init(LANG_SUCCESS,LANG_NETWORK_ADDED,MBOX_BTN_OK,eyefi_exit);
529 else
530 gui_mbox_init(LANG_FAILED,LANG_PROBLEM_ADDING_NETWORK,MBOX_BTN_OK,eyefi_exit);
531 }
532
533 static void password_cb(const char *str)
534 {
535 if (str == NULL)
536 {
537 eyefi_exit(0);
538 }
539 else
540 {
541 strncpy(eyefi_password, str, sizeof(eyefi_password)-1);
542 gui_mbox_init(LANG_ADD_NETWORK,LANG_TEST_NETWORK,MBOX_BTN_YES_NO|MBOX_DEF_BTN1,confirm_add_network_cb);
543 }
544 }
545
546 static void select_available_network_cb(unsigned nSelected)
547 {
548 unsigned flag=1;
549 int i,n;
550
551 if (nSelected == MPOPUP_CANCEL)
552 {
553 eyefi_exit(0);
554 return;
555 }
556
557 n = eyefi_buf.a.count;
558 for (i=0; i<n && i<MAX_NETWORK; i++)
559 {
560 if (nSelected == flag) break;
561 flag <<= 1;
562 }
563
564 if (nSelected != flag)
565 {
566 gui_mbox_init(LANG_ADD_NETWORK,LANG_CANNOT_FIND_NETWORK,MBOX_BTN_OK,eyefi_exit);
567 return;
568 }
569
570 strcpy(eyefi_selectedNetwork,eyefi_buf.a.nets[i].essid);
571 libtextbox->textbox_init((int)eyefi_selectedNetwork, LANG_PASSWORD, eyefi_password, PWD_LEN, password_cb, NULL);
572 }
573
574 static void eyefi_available_networks()
575 {
576 unsigned flag=1,flags=0;
577 int i,n;
578
579 running = 1;
580
581 if (eyefi_getAvailableNetworks() <= 0)
582 {
583 gui_mbox_init(LANG_ERROR_INITIALIZING_EYEFI,LANG_NO_EYEFI_CARD_FOUND,MBOX_BTN_OK,eyefi_exit);
584 }
585 else
586 {
587 memset(eyefi_selectedNetwork,0,sizeof(eyefi_selectedNetwork));
588 n = eyefi_buf.a.count;
589
590 if (n == 0)
591 {
592 gui_mbox_init(LANG_ADD_NETWORK,LANG_CANNOT_FIND_NETWORK,MBOX_BTN_OK,eyefi_exit);
593 }
594 else
595 {
596 for (i=0; i<n && i<MAX_NETWORK; i++)
597 {
598 popup_eyefi[i].text = (int)&(eyefi_buf.a.nets[i].essid);
599 popup_eyefi[i].flag = flag;
600 flags |= flag;
601 flag <<= 1;
602 }
603 popup_eyefi[i].text = (int)"Cancel";
604 popup_eyefi[i].flag = MPOPUP_CANCEL;
605
606 libmpopup->show_popup(popup_eyefi,flags,select_available_network_cb);
607 }
608 }
609 }
610
611
612 static void eyefi_wlan_off()
613 {
614 eyefi_wlan_state(0);
615 }
616
617 static void eyefi_wlan_on()
618 {
619 eyefi_wlan_state(1);
620 }
621
622 static CMenuItem eyefi_submenu_items[] = {
623 MENU_ITEM (0x5c,LANG_MENU_EYEFI_AVAILABLE_NETWORKS, MENUITEM_PROC, eyefi_available_networks, 0 ),
624 MENU_ITEM (0x5c,LANG_MENU_EYEFI_CONFIGURED_NETWORKS, MENUITEM_PROC, eyefi_configured_networks, 0 ),
625 MENU_ITEM (0x5c,LANG_FORCE_EYEFI_WLAN_OFF, MENUITEM_PROC, eyefi_wlan_off, 0 ),
626 MENU_ITEM (0x5c,LANG_FORCE_EYEFI_WLAN_ON, MENUITEM_PROC, eyefi_wlan_on, 0 ),
627 MENU_ITEM (0x51,LANG_MENU_BACK, MENUITEM_UP, 0, 0 ),
628 {0}
629 };
630
631 static CMenu eyefi_submenu = {0x21,LANG_MENU_EYEFI_TITLE, eyefi_submenu_items };
632
633
634 int _module_can_unload()
635 {
636 return (running == 0) || (get_curr_menu() != &eyefi_submenu);
637 }
638
639 int _run()
640 {
641 running = 1;
642 gui_activate_sub_menu(&eyefi_submenu);
643 return 0;
644 }
645
646 int _module_exit_alt()
647 {
648 running = 0;
649 return 0;
650 }
651
652 #include "simple_module.h"
653
654
655
656 libsimple_sym _libeyefi =
657 {
658 {
659 0, 0, _module_can_unload, _module_exit_alt, _run
660 },
661 };
662
663 ModuleInfo _module_info =
664 {
665 MODULEINFO_V1_MAGICNUM,
666 sizeof(ModuleInfo),
667 SIMPLE_MODULE_VERSION,
668
669 ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,
670 ANY_PLATFORM_ALLOWED,
671
672 -LANG_EYEFI,
673 MTYPE_TOOL|MTYPE_SUBMENU_TOOL,
674
675 &_libeyefi.base,
676
677 ANY_VERSION,
678 ANY_VERSION,
679 ANY_VERSION,
680 ANY_VERSION,
681
682 0,
683 };