Home | History | Annotate | Download | only in net
      1 /* rfkill.c - Enable/disable wireless devices.
      2  *
      3  * Copyright 2014 Ranjan Kumar <ranjankumar.bth (at) gmail.com>
      4  * Copyright 2014 Kyungwan Han <asura321 (at) gmail.com>
      5  *
      6  * No Standard
      7 
      8 USE_RFKILL(NEWTOY(rfkill, "<1>2", TOYFLAG_USR|TOYFLAG_SBIN))
      9 
     10 config RFKILL
     11   bool "rfkill"
     12   default y
     13   help
     14     Usage: rfkill COMMAND [DEVICE]
     15 
     16     Enable/disable wireless devices.
     17 
     18     Commands:
     19     list [DEVICE]   List current state
     20     block DEVICE    Disable device
     21     unblock DEVICE  Enable device
     22 
     23     DEVICE is an index number, or one of:
     24     all, wlan(wifi), bluetooth, uwb(ultrawideband), wimax, wwan, gps, fm.
     25 */
     26 
     27 #define FOR_rfkill
     28 #include "toys.h"
     29 #include <linux/rfkill.h>
     30 
     31 void rfkill_main(void)
     32 {
     33   struct rfkill_event rfevent;
     34   int fd, tvar, idx = -1, tid = RFKILL_TYPE_ALL;
     35   char **optargs = toys.optargs;
     36 
     37   // Parse command line options
     38   for (tvar = 0; tvar < 3; tvar++)
     39     if (!strcmp((char *[]){"list", "block", "unblock"}[tvar], *optargs)) break;
     40   if (tvar == 3) error_exit("unknown cmd '%s'", *optargs);
     41   if (tvar) {
     42     int i;
     43     struct arglist {
     44       char *name;
     45       int idx;
     46     } rftypes[] = {{"all", RFKILL_TYPE_ALL}, {"wifi", RFKILL_TYPE_WLAN},
     47       {"wlan", RFKILL_TYPE_WLAN}, {"bluetooth", RFKILL_TYPE_BLUETOOTH},
     48       {"uwb", RFKILL_TYPE_UWB}, {"ultrawideband", RFKILL_TYPE_UWB},
     49       {"wimax", RFKILL_TYPE_WIMAX}, {"wwan", RFKILL_TYPE_WWAN},
     50       {"gps", RFKILL_TYPE_GPS}, {"fm", 7}}; // RFKILL_TYPE_FM = 7
     51 
     52     if (!*++optargs) error_exit("'%s' needs IDENTIFIER", optargs[-1]);
     53     for (i = 0; i < ARRAY_LEN(rftypes); i++)
     54       if (!strcmp(rftypes[i].name, *optargs)) break;
     55     if (i == ARRAY_LEN(rftypes)) idx = atolx_range(*optargs, 0, INT_MAX);
     56     else tid = rftypes[i].idx;
     57   }
     58 
     59   // Perform requested action
     60   fd = xopen("/dev/rfkill", (tvar ? O_RDWR : O_RDONLY)|O_NONBLOCK);
     61   if (tvar) {
     62     // block/unblock
     63     memset(&rfevent, 0, sizeof(rfevent));
     64     rfevent.soft = tvar == 1;
     65     if (idx >= 0) {
     66       rfevent.idx = idx;
     67       rfevent.op = RFKILL_OP_CHANGE;
     68     } else {
     69       rfevent.type = tid;
     70       rfevent.op = RFKILL_OP_CHANGE_ALL;
     71     }
     72     xwrite(fd, &rfevent, sizeof(rfevent));
     73   } else {
     74     // show list.
     75     while (sizeof(rfevent) == readall(fd, &rfevent, sizeof(rfevent))) {
     76       char *line, *name = 0, *type = 0;
     77 
     78       // filter list items
     79       if ((tid > 0 && tid != rfevent.type) || (idx != -1 && idx != rfevent.idx))
     80         continue;
     81 
     82       sprintf(toybuf, "/sys/class/rfkill/rfkill%u/uevent", rfevent.idx);
     83       tvar = xopenro(toybuf);
     84       while ((line = get_line(tvar))) {
     85         char *s = line;
     86 
     87         if (strstart(&s, "RFKILL_NAME=")) name = xstrdup(s);
     88         else if (strstart(&s, "RFKILL_TYPE=")) type = xstrdup(s);
     89 
     90         free(line);
     91       }
     92       xclose(tvar);
     93 
     94       xprintf("%u: %s: %s\n", rfevent.idx, name, type);
     95       xprintf("\tSoft blocked: %s\n", rfevent.soft ? "yes" : "no");
     96       xprintf("\tHard blocked: %s\n", rfevent.hard ? "yes" : "no");
     97       free(name);
     98       free(type);
     99     }
    100   }
    101   xclose(fd);
    102 }
    103