39
39
#pragma GCC diagnostic pop
40
40
41
41
#define PORT_REPLY_SIZE (TUPLE_SIZE(2) + REF_SIZE)
42
+ #define DEFAULT_HOSTNAME_SIZE (strlen("atomvm-") + 12 + 1)
42
43
43
44
static const char * const ap_atom = ATOM_STR ("\x2" , "ap" );
44
45
static const char * const ap_channel_atom = ATOM_STR ("\xA" , "ap_channel" );
45
46
static const char * const ap_sta_connected_atom = ATOM_STR ("\x10" , "ap_sta_connected" );
46
47
static const char * const ap_sta_disconnected_atom = ATOM_STR ("\x13" , "ap_sta_disconnected" );
47
48
static const char * const ap_started_atom = ATOM_STR ("\xA" , "ap_started" );
49
+ static const char * const dhcp_hostname_atom = ATOM_STR ("\xD" , "dhcp_hostname" );
48
50
static const char * const host_atom = ATOM_STR ("\x4" , "host" );
49
51
static const char * const psk_atom = ATOM_STR ("\x3" , "psk" );
50
52
static const char * const sntp_atom = ATOM_STR ("\x4" , "sntp" );
@@ -79,6 +81,8 @@ struct NetworkDriverData
79
81
int stas_count ;
80
82
uint8_t * stas_mac ;
81
83
struct dhcp_config * dhcp_config ;
84
+ char * hostname ;
85
+ char * ap_hostname ;
82
86
queue_t queue ;
83
87
};
84
88
@@ -211,10 +215,29 @@ static void send_sntp_sync(struct timeval *tv)
211
215
END_WITH_STACK_HEAP (heap , driver_data -> global );
212
216
}
213
217
218
+ // param should be pointer to malloc'd destination to copy device hostname
219
+ // return ok atom or error as atom
220
+ static term get_default_device_name (char * name , GlobalContext * global )
221
+ {
222
+ uint8_t mac [6 ];
223
+ // Device name is used for AP mode ssid (if undefined), and for the
224
+ // default dhcp_hostname on both interfaces. It seems the interface
225
+ // parameter is ignored and both interfaces have the same MAC address.
226
+ int err = cyw43_wifi_get_mac (& cyw43_state , CYW43_ITF_STA , mac );
227
+ if (err ) {
228
+ return globalcontext_make_atom (global , ATOM_STR ("\x10" , "device_mac_error" ));
229
+ }
230
+ size_t buf_size = DEFAULT_HOSTNAME_SIZE ;
231
+ snprintf (name , buf_size ,
232
+ "atomvm-%02x%02x%02x%02x%02x%02x" , mac [0 ], mac [1 ], mac [2 ], mac [3 ], mac [4 ], mac [5 ]);
233
+ return OK_ATOM ;
234
+ }
235
+
214
236
static term start_sta (term sta_config , GlobalContext * global )
215
237
{
216
238
term ssid_term = interop_kv_get_value (sta_config , ssid_atom , global );
217
239
term pass_term = interop_kv_get_value (sta_config , psk_atom , global );
240
+ term hostname_term = interop_kv_get_value (sta_config , dhcp_hostname_atom , global );
218
241
219
242
//
220
243
// Check parameters
@@ -236,7 +259,54 @@ static term start_sta(term sta_config, GlobalContext *global)
236
259
}
237
260
}
238
261
239
- cyw43_arch_enable_sta_mode ();
262
+ if (term_is_invalid_term (hostname_term )) {
263
+ driver_data -> hostname = malloc (DEFAULT_HOSTNAME_SIZE );
264
+ if (IS_NULL_PTR (driver_data -> hostname )) {
265
+ free (ssid );
266
+ free (psk );
267
+ cyw43_arch_disable_sta_mode ();
268
+ return OUT_OF_MEMORY_ATOM ;
269
+ } else {
270
+ term error = get_default_device_name (driver_data -> hostname , global );
271
+ if (error != OK_ATOM ) {
272
+ free (ssid );
273
+ free (psk );
274
+ free (driver_data -> hostname );
275
+ cyw43_arch_disable_sta_mode ();
276
+ return error ;
277
+ }
278
+ }
279
+ } else {
280
+ int ok = 0 ;
281
+ char * buf = interop_term_to_string (hostname_term , & ok );
282
+ if (!ok || IS_NULL_PTR (buf )) {
283
+ free (ssid );
284
+ free (psk );
285
+ if (buf != NULL ) {
286
+ free (buf );
287
+ cyw43_arch_disable_sta_mode ();
288
+ return BADARG_ATOM ;
289
+ }
290
+ cyw43_arch_disable_sta_mode ();
291
+ return OUT_OF_MEMORY_ATOM ;
292
+ }
293
+ size_t buf_size = strlen (buf );
294
+ driver_data -> hostname = malloc (buf_size );
295
+ if (IS_NULL_PTR (driver_data -> hostname )) {
296
+ free (ssid );
297
+ free (psk );
298
+ free (buf );
299
+ cyw43_arch_disable_sta_mode ();
300
+ return OUT_OF_MEMORY_ATOM ;
301
+ }
302
+ memcpy (driver_data -> hostname , buf , buf_size );
303
+ free (buf );
304
+ }
305
+
306
+ // hostname must be set after enabling sta mode, because it is erased by
307
+ // cyw43_arch_enable_sta_mode and reset to factory "PicoW".
308
+ netif_set_hostname (& cyw43_state .netif [CYW43_ITF_STA ], driver_data -> hostname );
309
+
240
310
uint32_t auth = (psk == NULL ) ? CYW43_AUTH_OPEN : CYW43_AUTH_WPA2_MIXED_PSK ;
241
311
int result = cyw43_arch_wifi_connect_async (ssid , psk , auth );
242
312
// We need to set the callback after calling connect async because it's
@@ -247,32 +317,14 @@ static term start_sta(term sta_config, GlobalContext *global)
247
317
free (ssid );
248
318
free (psk );
249
319
if (result != 0 ) {
320
+ free (driver_data -> hostname );
321
+ cyw43_arch_disable_sta_mode ();
250
322
return BADARG_ATOM ;
251
323
}
252
324
253
325
return OK_ATOM ;
254
326
}
255
327
256
- static char * get_default_device_name ()
257
- {
258
- uint8_t mac [6 ];
259
- // Device name is used for AP mode. It seems the interface parameter is
260
- // ignored and both interfaces have the same MAC address.
261
- int err = cyw43_wifi_get_mac (& cyw43_state , CYW43_ITF_AP , mac );
262
- if (err ) {
263
- return NULL ;
264
- }
265
-
266
- size_t buf_size = strlen ("atomvm-" ) + 12 + 1 ;
267
- char * buf = malloc (buf_size );
268
- if (IS_NULL_PTR (buf )) {
269
- return NULL ;
270
- }
271
- snprintf (buf , buf_size ,
272
- "atomvm-%02x%02x%02x%02x%02x%02x" , mac [0 ], mac [1 ], mac [2 ], mac [3 ], mac [4 ], mac [5 ]);
273
- return buf ;
274
- }
275
-
276
328
static void network_driver_do_cyw43_assoc (GlobalContext * glb )
277
329
{
278
330
int max_stas ;
@@ -384,13 +436,23 @@ static term start_ap(term ap_config, GlobalContext *global)
384
436
term ssid_term = interop_kv_get_value (ap_config , ssid_atom , global );
385
437
term pass_term = interop_kv_get_value (ap_config , psk_atom , global );
386
438
term channel_term = interop_kv_get_value (ap_config , ap_channel_atom , global );
439
+ term hostname_term = interop_kv_get_value (ap_config , dhcp_hostname_atom , global );
387
440
388
441
//
389
442
// Check parameters
390
443
//
391
444
char * ssid = NULL ;
392
445
if (term_is_invalid_term (ssid_term )) {
393
- ssid = get_default_device_name ();
446
+ ssid = malloc (DEFAULT_HOSTNAME_SIZE );
447
+ if (IS_NULL_PTR (ssid )) {
448
+ return OUT_OF_MEMORY_ATOM ;
449
+ } else {
450
+ term error = get_default_device_name (ssid , global );
451
+ if (error != OK_ATOM ) {
452
+ free (ssid );
453
+ return error ;
454
+ }
455
+ }
394
456
} else {
395
457
int ok = 0 ;
396
458
ssid = interop_term_to_string (ssid_term , & ok );
@@ -419,9 +481,50 @@ static term start_ap(term ap_config, GlobalContext *global)
419
481
}
420
482
}
421
483
484
+ if (term_is_invalid_term (hostname_term )) {
485
+ driver_data -> ap_hostname = malloc (DEFAULT_HOSTNAME_SIZE );
486
+ if (IS_NULL_PTR (driver_data -> ap_hostname )) {
487
+ free (ssid );
488
+ free (psk );
489
+ return OUT_OF_MEMORY_ATOM ;
490
+ } else {
491
+ term error = get_default_device_name (driver_data -> ap_hostname , global );
492
+ if (error != OK_ATOM ) {
493
+ free (ssid );
494
+ free (psk );
495
+ free (driver_data -> ap_hostname );
496
+ return error ;
497
+ }
498
+ }
499
+ } else {
500
+ int ok = 0 ;
501
+ char * buf = interop_term_to_string (hostname_term , & ok );
502
+ if (UNLIKELY (!ok || buf == NULL )) {
503
+ free (ssid );
504
+ free (psk );
505
+ if (buf != NULL ) {
506
+ free (buf );
507
+ return ERROR_ATOM ;
508
+ }
509
+ return OUT_OF_MEMORY_ATOM ;
510
+ }
511
+ size_t buf_size = strlen (buf );
512
+ driver_data -> ap_hostname = malloc (buf_size );
513
+ if (IS_NULL_PTR (driver_data -> ap_hostname )) {
514
+ free (ssid );
515
+ free (psk );
516
+ free (buf );
517
+ return OUT_OF_MEMORY_ATOM ;
518
+ }
519
+ memcpy (driver_data -> ap_hostname , buf , buf_size );
520
+ free (buf );
521
+ }
522
+
422
523
uint32_t auth = (psk == NULL ) ? CYW43_AUTH_OPEN : CYW43_AUTH_WPA2_AES_PSK ;
423
524
cyw43_state .assoc_cb = network_driver_cyw43_assoc_cb ;
424
525
cyw43_arch_enable_ap_mode (ssid , psk , auth );
526
+ // Set hostname after enabling AP mode otherwise hostname will revert to "PicoW"
527
+ netif_set_hostname (& cyw43_state .netif [CYW43_ITF_AP ], driver_data -> ap_hostname );
425
528
send_ap_started (global );
426
529
free (ssid );
427
530
free (psk );
@@ -574,17 +677,18 @@ static void start_network(Context *ctx, term pid, term ref, term config)
574
677
return ;
575
678
}
576
679
680
+ // Always enable sta mode so the bus is initialized and we get a MAC
681
+ // address. This is done before configuring the interface because the
682
+ // MAC is added to the default hostname, and default ssid in ap mode.
683
+ // (i.e. atomvm-0123456789ab)
684
+ cyw43_arch_enable_sta_mode ();
577
685
if (!term_is_invalid_term (sta_config )) {
578
686
term result_atom = start_sta (sta_config , ctx -> global );
579
687
if (result_atom != OK_ATOM ) {
580
688
term error = port_create_error_tuple (ctx , result_atom );
581
689
port_send_reply (ctx , pid , ref , error );
582
690
return ;
583
691
}
584
- } else {
585
- // Always enable sta mode so the bus is initialized and we get a MAC
586
- // address.
587
- cyw43_arch_enable_sta_mode ();
588
692
}
589
693
590
694
if (!term_is_invalid_term (ap_config )) {
@@ -705,6 +809,10 @@ void network_driver_init(GlobalContext *global)
705
809
void network_driver_destroy (GlobalContext * global )
706
810
{
707
811
if (driver_data ) {
812
+ free (driver_data -> hostname );
813
+ if (driver_data -> ap_hostname ) {
814
+ free (driver_data -> ap_hostname );
815
+ }
708
816
free (driver_data -> sntp_hostname );
709
817
free (driver_data -> stas_mac );
710
818
if (driver_data -> dhcp_config ) {
0 commit comments