* gnu/installer/steps.scm (run-installer-steps): Set up 'installer-step prompt. * gnu/installer/newt/ethernet.scm (run-ethernet-page) * gnu/installer/newt/final.scm (run-config-display-page, run-install-failed-page) * gnu/installer/newt/keymap.scm (run-layout-page, run-variant-page) * gnu/installer/newt/locale.scm (run-language-page, run-territory-page, run-codeset-page, run-modifier-page, run-locale-page) * gnu/installer/newt/network.scm (run-technology-page, wait-service-online) * gnu/installer/newt/page.scm (run-listbox-selection-page, run-checkbox-tree-page) * gnu/installer/newt/partition.scm (button-exit-action) * gnu/installer/newt/services.scm (run-desktop-environments-cbt-page, run-networking-cbt-page, run-other-services-cbt-page, run-network-management-page) * gnu/installer/newt/timezone.scm (run-timezone-page) * gnu/installer/newt/user.scm (run-user-page) * gnu/installer/newt/welcome.scm (run-menu-page) * gnu/installer/newt/wifi.scm (run-wifi-page): Use the 'installer-step prompt to abort. Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
		
			
				
	
	
		
			246 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
| ;;; GNU Guix --- Functional package management for GNU
 | |
| ;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
 | |
| ;;; Copyright © 2019 Meiyo Peng <meiyo@riseup.net>
 | |
| ;;; Copyright © 2019 Tobias Geerinckx-Rice <me@tobias.gr>
 | |
| ;;;
 | |
| ;;; This file is part of GNU Guix.
 | |
| ;;;
 | |
| ;;; GNU Guix is free software; you can redistribute it and/or modify it
 | |
| ;;; under the terms of the GNU General Public License as published by
 | |
| ;;; the Free Software Foundation; either version 3 of the License, or (at
 | |
| ;;; your option) any later version.
 | |
| ;;;
 | |
| ;;; GNU Guix is distributed in the hope that it will be useful, but
 | |
| ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| ;;; GNU General Public License for more details.
 | |
| ;;;
 | |
| ;;; You should have received a copy of the GNU General Public License
 | |
| ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| (define-module (gnu installer newt wifi)
 | |
|   #:use-module (gnu installer connman)
 | |
|   #:use-module (gnu installer steps)
 | |
|   #:use-module (gnu installer newt utils)
 | |
|   #:use-module (gnu installer newt page)
 | |
|   #:use-module (guix i18n)
 | |
|   #:use-module (guix records)
 | |
|   #:use-module (ice-9 format)
 | |
|   #:use-module (ice-9 popen)
 | |
|   #:use-module (ice-9 receive)
 | |
|   #:use-module (ice-9 regex)
 | |
|   #:use-module (ice-9 rdelim)
 | |
|   #:use-module (srfi srfi-1)
 | |
|   #:use-module (srfi srfi-34)
 | |
|   #:use-module (srfi srfi-35)
 | |
|   #:use-module (newt)
 | |
|   #:export (run-wifi-page))
 | |
| 
 | |
| ;; This record associates a connman service to its key the listbox.
 | |
| (define-record-type* <service-item>
 | |
|   service-item make-service-item
 | |
|   service-item?
 | |
|   (service   service-item-service) ; connman <service>
 | |
|   (key       service-item-key)) ; newt listbox-key
 | |
| 
 | |
| (define (strength->string strength)
 | |
|   "Convert STRENGTH as an integer percentage into a text printable strength
 | |
| bar using unicode characters. Taken from NetworkManager's
 | |
| nmc_wifi_strength_bars."
 | |
|   (let ((quarter #\x2582)
 | |
|         (half #\x2584)
 | |
|         (three-quarter #\x2586)
 | |
|         (full #\x2588))
 | |
|     (cond
 | |
|      ((> strength 80)
 | |
|       ;; ▂▄▆█
 | |
|       (string quarter half three-quarter full))
 | |
|      ((> strength 55)
 | |
|       ;; ▂▄▆_
 | |
|       (string quarter half three-quarter #\_))
 | |
|      ((> strength 30)
 | |
|       ;; ▂▄__
 | |
|       (string quarter half #\_ #\_))
 | |
|      ((> strength 5)
 | |
|       ;; ▂___
 | |
|       (string quarter #\_ #\_ #\_))
 | |
|      (else
 | |
|       ;; ____
 | |
|       (string quarter #\_ #\_ #\_ #\_)))))
 | |
| 
 | |
| (define (force-wifi-scan)
 | |
|   "Force a wifi scan. Raise a condition if no wifi technology is available."
 | |
|   (let* ((technologies (connman-technologies))
 | |
|          (wifi-technology
 | |
|           (find (lambda (technology)
 | |
|                   (string=? (technology-type technology) "wifi"))
 | |
|                 technologies)))
 | |
|     (if wifi-technology
 | |
|         (connman-scan-technology wifi-technology)
 | |
|         (raise (condition
 | |
|                 (&message
 | |
|                  (message (G_ "Unable to find a wifi technology"))))))))
 | |
| 
 | |
| (define (draw-scanning-page)
 | |
|   "Draw a page to indicate a wifi scan in progress."
 | |
|   (draw-info-page (G_ "Scanning wifi for available networks, please wait.")
 | |
|                   (G_ "Scan in progress")))
 | |
| 
 | |
| (define (run-wifi-password-page)
 | |
|   "Run a page prompting user for a password and return it."
 | |
|   (run-input-page (G_ "Please enter the wifi password.")
 | |
|                   (G_ "Password required")
 | |
|                   #:input-visibility-checkbox? #t))
 | |
| 
 | |
| (define (run-wrong-password-page service-name)
 | |
|   "Run a page to inform user of a wrong password input."
 | |
|   (run-error-page
 | |
|    (format #f (G_ "The password you entered for ~a is incorrect.")
 | |
|            service-name)
 | |
|    (G_ "Wrong password")))
 | |
| 
 | |
| (define (run-unknown-error-page service-name)
 | |
|   "Run a page to inform user that a connection error happened."
 | |
|   (run-error-page
 | |
|    (format #f
 | |
|            (G_ "An error occurred while trying to connect to ~a, please retry.")
 | |
|            service-name)
 | |
|    (G_ "Connection error")))
 | |
| 
 | |
| (define (password-callback)
 | |
|   (run-wifi-password-page))
 | |
| 
 | |
| (define (connect-wifi-service listbox service-items)
 | |
|   "Connect to the wifi service selected in LISTBOX. SERVICE-ITEMS is the list
 | |
| of <service-item> records present in LISTBOX."
 | |
|   (let* ((listbox-key (current-listbox-entry listbox))
 | |
|          (item (find (lambda (item)
 | |
|                        (eq? (service-item-key item) listbox-key))
 | |
|                      service-items))
 | |
|          (service (service-item-service item))
 | |
|          (service-name (service-name service))
 | |
|          (form (draw-connecting-page service-name)))
 | |
|     (dynamic-wind
 | |
|       (const #t)
 | |
|       (lambda ()
 | |
|         (guard (c ((connman-password-error? c)
 | |
|                    (run-wrong-password-page service-name)
 | |
|                    #f)
 | |
|                   ((connman-already-connected-error? c)
 | |
|                    #t)
 | |
|                   ((connman-connection-error? c)
 | |
|                    (run-unknown-error-page service-name)
 | |
|                    #f))
 | |
|           (connman-connect-with-auth service password-callback)))
 | |
|       (lambda ()
 | |
|         (destroy-form-and-pop form)))))
 | |
| 
 | |
| (define (run-wifi-scan-page)
 | |
|   "Force a wifi scan and draw a page during the operation."
 | |
|   (let ((form (draw-scanning-page)))
 | |
|     (force-wifi-scan)
 | |
|     (destroy-form-and-pop form)))
 | |
| 
 | |
| (define (wifi-services)
 | |
|   "Return all the connman services of wifi type."
 | |
|   (let ((services (connman-services)))
 | |
|     (filter (lambda (service)
 | |
|               (and (string=? (service-type service) "wifi")
 | |
|                    (service-name service)
 | |
|                    (not (string-null? (service-name service)))))
 | |
|             services)))
 | |
| 
 | |
| (define* (fill-wifi-services listbox wifi-services)
 | |
|   "Append all the services in WIFI-SERVICES to the given LISTBOX."
 | |
|   (clear-listbox listbox)
 | |
|   (map (lambda (service)
 | |
|          (let* ((text (service->text service))
 | |
|                 (key (append-entry-to-listbox listbox text)))
 | |
|            (service-item
 | |
|             (service service)
 | |
|             (key key))))
 | |
|        wifi-services))
 | |
| 
 | |
| ;; Maximum length of a wifi service name.
 | |
| (define service-name-max-length (make-parameter 20))
 | |
| 
 | |
| ;; Height of the listbox displaying wifi services.
 | |
| (define wifi-listbox-height (make-parameter
 | |
|                              (default-listbox-height)))
 | |
| 
 | |
| ;; Information textbox width.
 | |
| (define info-textbox-width (make-parameter 40))
 | |
| 
 | |
| (define (service->text service)
 | |
|   "Return a string composed of the name and the strength of the given
 | |
| SERVICE. A '*' preceding the service name indicates that it is connected."
 | |
|   (let* ((name (service-name service))
 | |
|          (padded-name (string-pad-right name
 | |
|                                         (service-name-max-length)))
 | |
|          (strength (service-strength service))
 | |
|          (strength-string (strength->string strength))
 | |
|          (state (service-state service))
 | |
|          (connected? (or (string=? state "online")
 | |
|                          (string=? state "ready"))))
 | |
|     (format #f "~c ~a ~a~%"
 | |
|             (if connected? #\* #\ )
 | |
|             padded-name
 | |
|             strength-string)))
 | |
| 
 | |
| (define (run-wifi-page)
 | |
|   "Run a page displaying available wifi networks in a listbox. Connect to the
 | |
| network when the corresponding listbox entry is selected. A button allow to
 | |
| force a wifi scan."
 | |
|   (let* ((listbox (make-listbox
 | |
|                    -1 -1
 | |
|                    (wifi-listbox-height)
 | |
|                    (logior FLAG-SCROLL FLAG-BORDER FLAG-RETURNEXIT)))
 | |
|          (form (make-form))
 | |
|          (buttons-grid (make-grid 1 1))
 | |
|          (middle-grid (make-grid 2 1))
 | |
|          (info-text (G_ "Please select a wifi network."))
 | |
|          (info-textbox
 | |
|           (make-reflowed-textbox -1 -1 info-text
 | |
|                                  (info-textbox-width)
 | |
|                                  #:flags FLAG-BORDER))
 | |
|          (exit-button (make-button -1 -1 (G_ "Exit")))
 | |
|          (scan-button (make-button -1 -1 (G_ "Scan")))
 | |
|          (services (wifi-services))
 | |
|          (service-items '()))
 | |
| 
 | |
|     (if (null? services)
 | |
|         (append-entry-to-listbox listbox (G_ "No wifi detected"))
 | |
|         (set! service-items (fill-wifi-services listbox services)))
 | |
| 
 | |
|     (set-grid-field middle-grid 0 0 GRID-ELEMENT-COMPONENT listbox)
 | |
|     (set-grid-field middle-grid 1 0 GRID-ELEMENT-COMPONENT scan-button
 | |
|                     #:anchor ANCHOR-TOP
 | |
|                     #:pad-left 2)
 | |
|     (set-grid-field buttons-grid 0 0 GRID-ELEMENT-COMPONENT exit-button)
 | |
| 
 | |
|     (add-components-to-form form
 | |
|                             info-textbox
 | |
|                             listbox scan-button
 | |
|                             exit-button)
 | |
|     (make-wrapped-grid-window
 | |
|      (basic-window-grid info-textbox middle-grid buttons-grid)
 | |
|      (G_ "Wifi"))
 | |
| 
 | |
|     (receive (exit-reason argument)
 | |
|         (run-form form)
 | |
|       (dynamic-wind
 | |
|         (const #t)
 | |
|         (lambda ()
 | |
|           (when (eq? exit-reason 'exit-component)
 | |
|             (cond
 | |
|              ((components=? argument scan-button)
 | |
|               (run-wifi-scan-page)
 | |
|               (run-wifi-page))
 | |
|              ((components=? argument exit-button)
 | |
|               (abort-to-prompt 'installer-step 'abort))
 | |
|              ((components=? argument listbox)
 | |
|               (let ((result (connect-wifi-service listbox service-items)))
 | |
|                 (unless result
 | |
|                   (run-wifi-page)))))))
 | |
|         (lambda ()
 | |
|           (destroy-form-and-pop form))))))
 |