Example #1
0
/*
 * Add udev info.
 */
void int_udev(hd_data_t *hd_data)
{
  hd_udevinfo_t *ui;
  hd_t *hd;
  str_list_t *sl;

  if(!hd_data->udevinfo) read_udevinfo(hd_data);

  if(!hd_data->udevinfo) return;

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(!hd->unix_dev_names && hd->unix_dev_name) {
      add_str_list(&hd->unix_dev_names, hd->unix_dev_name);
    }

    if(!hd->sysfs_id) continue;

    for(ui = hd_data->udevinfo; ui; ui = ui->next) {
      if(ui->name && !strcmp(ui->sysfs, hd->sysfs_id)) {
        if(!search_str_list(hd->unix_dev_names, ui->name)) {
          add_str_list(&hd->unix_dev_names, ui->name);
        }
        for(sl = ui->links; sl; sl = sl->next) {
          if(!search_str_list(hd->unix_dev_names, sl->str)) {
            add_str_list(&hd->unix_dev_names, sl->str);
          }
        }

        if(!hd->unix_dev_name || hd_data->flags.udev) {
          sl = hd->unix_dev_names;

          if(hd_data->flags.udev) {
            /* use first link as canonical device name */
            if(ui->links) sl = sl->next;
          }

          hd->unix_dev_name = new_str(sl->str);
        }

        break;
      }
    }
  }

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(!hd->unix_dev_names) continue;

    for(ui = hd_data->udevinfo; ui; ui = ui->next) {
      if(search_str_list(hd->unix_dev_names, ui->name)) {
        for(sl = ui->links; sl; sl = sl->next) {
          if(!search_str_list(hd->unix_dev_names, sl->str)) {
            add_str_list(&hd->unix_dev_names, sl->str);
          }
        }
      }
    }
  }
}
Example #2
0
/*
 * Remove usb entries that are handled by usb-storage.
 */
void int_fix_usb_scsi(hd_data_t *hd_data)
{
  hd_t *hd_scsi, *hd_usb;

  for(hd_usb = hd_data->hd; hd_usb; hd_usb= hd_usb->next) {
    if(
      hd_usb->bus.id == bus_usb &&
      hd_usb->sysfs_id &&
      search_str_list(hd_usb->drivers, "usb-storage")
    ) {
      for(hd_scsi = hd_data->hd; hd_scsi; hd_scsi = hd_scsi->next) {
        if(
          hd_scsi->bus.id == bus_scsi &&
          hd_scsi->sysfs_device_link &&
          search_str_list(hd_scsi->drivers, "usb-storage")
        ) {
          if(!strncmp(hd_scsi->sysfs_device_link, hd_usb->sysfs_id, strlen(hd_usb->sysfs_id))) {
            hd_set_hw_class(hd_scsi, hw_usb);

            free_mem(hd_scsi->unique_id);
            hd_scsi->unique_id = hd_usb->unique_id;
            hd_usb->unique_id = NULL;

            add_res_entry(&hd_scsi->res, hd_usb->res);
            hd_usb->res = NULL;

            if(!hd_scsi->modalias) {
              hd_scsi->modalias = hd_usb->modalias;
              hd_usb->modalias = NULL;
            }

            if(!hd_scsi->vendor.id) hd_scsi->vendor.id = hd_usb->vendor.id;
            if(!hd_scsi->device.id) hd_scsi->device.id = hd_usb->device.id;

            if(!hd_scsi->serial) {
              hd_scsi->serial = hd_usb->serial;
              hd_usb->serial = NULL;
            }

            if(!hd_scsi->driver_info) {
              hd_scsi->driver_info = hd_usb->driver_info;
              hd_usb->driver_info = NULL;
            }

            new_id(hd_data, hd_scsi);

            hd_usb->tag.remove = 1;
          }
        }
      }
    }
  }

  remove_tagged_hd_entries(hd_data);
}
Example #3
0
/*
 * If hd->unix_dev_name is not in hd->unix_dev_names, add it.
 */
void int_devicenames(hd_data_t *hd_data)
{
  hd_t *hd;

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->unix_dev_name &&
      !search_str_list(hd->unix_dev_names, hd->unix_dev_name)
    ) {
      add_str_list(&hd->unix_dev_names, hd->unix_dev_name);
    }
  }
}
Example #4
0
/*
 * Tag ide soft raid disks.
 */
void int_softraid(hd_data_t *hd_data)
{
  hd_t *hd;
  str_list_t *raid, *sl, *raid_sysfs = NULL, *sl1;
  size_t len;
  char *s;

  if(hd_data->flags.fast) return;

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_storage_device &&
      hd->status.available != status_no
    ) break;
  }

  /* no disks -> no check necessary */
  if(!hd) return;
  
  raid = read_file("| /sbin/dmraid -rc 2>/dev/null", 0, 0);

  for(sl = raid; sl; sl = sl->next) {
    s = *sl->str ? strchr(sl->str + 1, '/') : NULL;
    if(s) {
      sl1 = add_str_list(&raid_sysfs, NULL);
      str_printf(&sl1->str, 0, "/block%s", s);
      len = strlen(sl1->str);
      if(len) sl1->str[len - 1] = 0;
    }
  }

  free_str_list(raid);

  ADD2LOG("----- soft raid devices -----\n");
  for(sl = raid_sysfs; sl; sl = sl->next) {
    ADD2LOG("  %s\n", sl->str);
  }
  ADD2LOG("----- soft raid devices end -----\n");

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(search_str_list(raid_sysfs, hd->sysfs_id)) {
      hd->is.softraiddisk = 1;
    }
  }

  free_str_list(raid_sysfs);

}
Example #5
0
void get_usb_devs(hd_data_t *hd_data)
{
  uint64_t ul0;
  unsigned u1, u2, u3;
  hd_t *hd, *hd1;
  usb_t *usb;
  str_list_t *sl, *usb_devs = NULL;
  char *s, *s1, *t;
  hd_res_t *res;
  size_t l;
  str_list_t *sf_bus, *sf_bus_e;
  char *sf_dev, *sf_dev_2;

  sf_bus = read_dir("/sys/bus/usb/devices", 'l');

  if(!sf_bus) {
    ADD2LOG("sysfs: no such bus: usb\n");
    return;
  }

  for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) {
    sf_dev = hd_read_sysfs_link("/sys/bus/usb/devices", sf_bus_e->str);

    if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bNumInterfaces"), &ul0, 0)) {
      add_str_list(&usb_devs, sf_dev);
      ADD2LOG("  usb dev: %s\n", hd_sysfs_id(sf_dev));
    }
  }

  for(sf_bus_e = sf_bus; sf_bus_e; sf_bus_e = sf_bus_e->next) {
    sf_dev = new_str(hd_read_sysfs_link("/sys/bus/usb/devices", sf_bus_e->str));

    ADD2LOG(
      "  usb device: name = %s\n    path = %s\n",
      sf_bus_e->str,
      hd_sysfs_id(sf_dev)
    );

    if(
      hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceNumber"), &ul0, 16)
    ) {
      hd = add_hd_entry(hd_data, __LINE__, 0);

      hd->detail = new_mem(sizeof *hd->detail);
      hd->detail->type = hd_detail_usb;
      hd->detail->usb.data = usb = new_mem(sizeof *usb);

      hd->sysfs_id = new_str(hd_sysfs_id(sf_dev));
      hd->sysfs_bus_id = new_str(sf_bus_e->str);

      hd->bus.id = bus_usb;
      hd->func = ul0;

      usb->ifdescr = ul0;

      if((s = get_sysfs_attr_by_path(sf_dev, "modalias"))) {
        s = canon_str(s, strlen(s));
        ADD2LOG("    modalias = \"%s\"\n", s);
        if(s && *s) {
          hd->modalias = s;
          s = NULL;
        }
        s = free_mem(s);
      }

      ADD2LOG("    bInterfaceNumber = %u\n", hd->func);

      if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceClass"), &ul0, 16)) {
        usb->i_cls = ul0;
        ADD2LOG("    bInterfaceClass = %u\n", usb->i_cls);
      }

      if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceSubClass"), &ul0, 16)) {
        usb->i_sub = ul0;
        ADD2LOG("    bInterfaceSubClass = %u\n", usb->i_sub);
      }

      if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev, "bInterfaceProtocol"), &ul0, 16)) {
        usb->i_prot = ul0;
        ADD2LOG("    bInterfaceProtocol = %u\n", usb->i_prot);
      }

      /* device has longest matching sysfs id */
      u2 = strlen(sf_dev);
      s = NULL;
      for(u3 = 0, sl = usb_devs; sl; sl = sl->next) {
        u1 = strlen(sl->str);
        if(u1 > u3 && u1 <= u2 && !strncmp(sf_dev, sl->str, u1)) {
          u3 = u1;
          s = sl->str;
        }
      }

      if(s) {
        ADD2LOG("    if: %s @ %s\n", hd->sysfs_bus_id, hd_sysfs_id(s));
        sf_dev_2 = new_str(s);
        if(sf_dev_2) {

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceClass"), &ul0, 16)) {
            usb->d_cls = ul0;
            ADD2LOG("    bDeviceClass = %u\n", usb->d_cls);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceSubClass"), &ul0, 16)) {
            usb->d_sub = ul0;
            ADD2LOG("    bDeviceSubClass = %u\n", usb->d_sub);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bDeviceProtocol"), &ul0, 16)) {
            usb->d_prot = ul0;
            ADD2LOG("    bDeviceProtocol = %u\n", usb->d_prot);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "idVendor"), &ul0, 16)) {
            usb->vendor = ul0;
            ADD2LOG("    idVendor = 0x%04x\n", usb->vendor);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "idProduct"), &ul0, 16)) {
            usb->device = ul0;
            ADD2LOG("    idProduct = 0x%04x\n", usb->device);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "manufacturer"))) {
            usb->manufact = canon_str(s, strlen(s));
            ADD2LOG("    manufacturer = \"%s\"\n", usb->manufact);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "product"))) {
            usb->product = canon_str(s, strlen(s));
            ADD2LOG("    product = \"%s\"\n", usb->product);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "serial"))) {
            usb->serial = canon_str(s, strlen(s));
            ADD2LOG("    serial = \"%s\"\n", usb->serial);
          }

          if(hd_attr_uint(get_sysfs_attr_by_path(sf_dev_2, "bcdDevice"), &ul0, 16)) {
            usb->rev = ul0;
            ADD2LOG("    bcdDevice = %04x\n", usb->rev);
          }

          if((s = get_sysfs_attr_by_path(sf_dev_2, "speed"))) {
            s = canon_str(s, strlen(s));
            if(!strcmp(s, "1.5")) usb->speed = 15*100000;
            else if(!strcmp(s, "12")) usb->speed = 12*1000000;
            else if(!strcmp(s, "480")) usb->speed = 480*1000000;
            ADD2LOG("    speed = \"%s\"\n", s);
            s = free_mem(s);
          }

          sf_dev_2 = free_mem(sf_dev_2);
        }
      }

      if(usb->vendor || usb->device) {
        hd->vendor.id = MAKE_ID(TAG_USB, usb->vendor);
        hd->device.id = MAKE_ID(TAG_USB, usb->device);
      }

      if(usb->manufact) hd->vendor.name = new_str(usb->manufact);
      if(usb->product) hd->device.name = new_str(usb->product);
      if(usb->serial) hd->serial = new_str(usb->serial);

      if(usb->rev) str_printf(&hd->revision.name, 0, "%x.%02x", usb->rev >> 8, usb->rev & 0xff);

      if(usb->speed) {
        res = add_res_entry(&hd->res, new_mem(sizeof *res));
        res->baud.type = res_baud;
        res->baud.speed = usb->speed;
      }

      s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1);
      if(s) add_str_list(&hd->drivers, s);

      set_class_entries(hd_data, hd, usb);

      if(!hd_data->scanner_db) {
        hd_data->scanner_db = hd_module_list(hd_data, 1);
      }

      if(
        hd->drivers &&
        search_str_list(hd_data->scanner_db, hd->drivers->str)
      ) {
        hd->base_class.id = bc_scanner;
      }

      // ###### FIXME
      if(hd->base_class.id == bc_modem) {
        hd->unix_dev_name = new_str("/dev/ttyACM0");
      }
    }

    sf_dev = free_mem(sf_dev);
  }
Example #6
0
/*
 * Improve mouse info.
 */
void int_mouse(hd_data_t *hd_data)
{
  hd_t *hd;
  bios_info_t *bt = NULL;

#if 0
  str_list_t *sl;
  int is_mouse;

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->bus.id != bus_usb ||
      hd->base_class.id != bc_mouse ||
      hd->sub_class.id != sc_mou_usb ||
      !search_str_list(hd->drivers, "usbhid")
    ) continue;

    is_mouse = 0;

    for(sl = hd->unix_dev_names; sl; sl = sl->next) {
      if(strstr(sl->str, "/mice") || strstr(sl->str, "/mouse")) {
        is_mouse = 1;
        break;
      }
    }

    if(!is_mouse) {
      if(
        (hd->unix_dev_name && strstr(hd->unix_dev_name, "/mice")) ||
        (hd->unix_dev_name2 && strstr(hd->unix_dev_name2, "/mouse"))
      ) {
        is_mouse = 1;
      }
    }

    /* not really a mouse */
    if(!is_mouse) {
      hd->base_class.id = 0;
      hd->sub_class.id = 0;
      hd->compat_vendor.id = 0;
      hd->compat_device.id = 0;
    }
  }
#endif

  if(hd_data->flags.vbox || hd_data->flags.vmware_mouse) {
    for(hd = hd_data->hd; hd; hd = hd->next) {
      if(
        hd->base_class.id == bc_mouse &&
        hd->sub_class.id == sc_mou_ps2 &&
        hd->vendor.id == 2
      ) {
        if(hd_data->flags.vbox && hd->device.id == 6) {
          hd->vendor.name = free_mem(hd->vendor.name);
          hd->device.name = free_mem(hd->device.name);
          hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x80ee);
          hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0100);
          new_id(hd_data, hd);
        }
        else if(hd_data->flags.vmware && hd->device.id == 5) {
          hd->vendor.name = free_mem(hd->vendor.name);
          hd->device.name = free_mem(hd->device.name);
          hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x15ad);
          hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0100);
          new_id(hd_data, hd);
        }
        else if(hd_data->flags.vmware_mouse && hd->device.id == 6) {
          hd->vendor.name = free_mem(hd->vendor.name);
          hd->device.name = free_mem(hd->device.name);
          // hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6014);
          hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x15ad);
          hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0100);
          new_id(hd_data, hd);
        }
      }
    }
  }

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->detail &&
      hd->detail->type == hd_detail_bios &&
      (bt = hd->detail->bios.data) &&
      bt->mouse.type
    ) break;
  }

  if(!bt) return;

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_mouse &&
      hd->sub_class.id == sc_mou_ps2 &&
      hd->bus.id == bt->mouse.bus &&
      hd->vendor.id == MAKE_ID(TAG_SPECIAL, 0x0200) &&
      hd->device.id == MAKE_ID(TAG_SPECIAL, 0x0002)
    ) {
      hd->vendor.name = free_mem(hd->vendor.name);
      hd->device.name = free_mem(hd->device.name);
      hd->vendor.id = hd->device.id = 0;
#if 0
      hd->vendor.id = bt->mouse.compat_vend;
      hd->device.id = bt->mouse.compat_dev;
#else
      hd->vendor.name = new_str(bt->mouse.vendor);
      hd->device.name = new_str(bt->mouse.type);
      hd->compat_vendor.id = bt->mouse.compat_vend;
      hd->compat_device.id = bt->mouse.compat_dev;
#endif
      new_id(hd_data, hd);
    }
  }
}
Example #7
0
/*
 * Send a list of the search result to the client.
 */
void command_lists(sp_session *session, const struct command * const command)
{
	sock_send_str(command->sockfd, search_str_list());
}
Example #8
0
void hd_scan_wlan(hd_data_t *hd_data)
{
  hd_t *hd;
  hd_res_t *res;
  struct iw_range range;
  int k;
  int skfd;
  struct wpa_driver_ops *wpa_drv=NULL;

  if(!hd_probe_feature(hd_data, pr_wlan)) return;

  hd_data->module = mod_wlan;

  PROGRESS(1, 0, "detecting wlan features");

  if ((skfd = iw_sockets_open()) < 0) {
    ADD2LOG( "could not open socket, wlan feature query failed\n" );
    return;
  }

  for(hd = hd_data->hd; hd; hd = hd->next) {
    if(
      hd->base_class.id == bc_network &&
      hd->unix_dev_name ) {
      /* Get list of frequencies / channels */
      if(iw_get_range_info(skfd, hd->unix_dev_name, &range) < 0) {
	/* this failed, maybe device does not support wireless extensions */
	continue;
      }
      ADD2LOG("*** device %s is wireless ***\n", hd->unix_dev_name);
      hd->is.wlan = 1;

      hd->sub_class.id = 0x82;		/* wlan */

      res = new_mem(sizeof *res);
      res->any.type = res_wlan;

      if(range.num_frequency > 0) {
	char buff[20];
	for(k = 0; k < range.num_frequency; k++) {
	  snprintf(buff, 19, "%i", range.freq[k].i);
	  add_str_list(&res->wlan.channels, buff);
	  snprintf(buff, 19, "%g", (float)iw_freq2float(&(range.freq[k]))/1000000000);
	  add_str_list(&res->wlan.frequencies, buff);
	}
	for(k = 0; k < range.num_bitrates; k++) {
	  snprintf(buff, 19, "%g", (float)range.bitrate[k]/1000000);
	  add_str_list(&res->wlan.bitrates, buff);
	}
	for(k = 0; k < range.num_encoding_sizes; k++) {
	  snprintf(buff, 19, "WEP%i", range.encoding_size[k]*8);
	  add_str_list(&res->wlan.enc_modes, buff);
	}

	/* open mode is always supported */
	add_str_list(&res->wlan.auth_modes, "open");
	/* if WEP is supported, be assume shared key auth support */
	if(range.num_encoding_sizes) {
	  add_str_list(&res->wlan.auth_modes, "sharedkey");
	}

	/* detect WPA capabilities */
	if (!hd_data->flags.nowpa && hd->drivers) {
	  if (search_str_list(hd->drivers, "ath_pci"))
	    wpa_drv = &wpa_driver_madwifi_ops;
	  else if (strncmp(hd->drivers->str, "at76", 4)==0)
	    wpa_drv = &wpa_driver_atmel_ops;
	  else 
	    wpa_drv = &wpa_driver_wext_ops;
	}
	
	if (wpa_drv) {
	  if (wpa_drv->set_wpa(hd->unix_dev_name, 1) == 0) {
	    add_str_list(&res->wlan.auth_modes, "wpa-psk");
	    add_str_list(&res->wlan.auth_modes, "wpa-eap");
	    if (wpa_drv->set_auth_alg && 
		wpa_drv->set_auth_alg(hd->unix_dev_name, AUTH_ALG_LEAP)==0)
	      add_str_list(&res->wlan.auth_modes, "wpa-leap");
	    if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_TKIP, "ff:ff:ff:ff:ff:ff",
				 0, 0, 0, 0,
				 "00000000000000000000000000000000", 32) ==0)
	      add_str_list(&res->wlan.enc_modes, "TKIP");
	    if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_CCMP, "ff:ff:ff:ff:ff:ff",
				 0, 0, 0, 0, 
				 "0000000000000000", 16) ==0)
	      add_str_list(&res->wlan.enc_modes, "CCMP");
	    wpa_drv->set_wpa(hd->unix_dev_name, 0);
	  }
	}
      }
      add_res_entry(&hd->res, res);
    }
  }
}
Example #9
0
void get_input_devices(hd_data_t *hd_data)
{
  hd_t *hd;
  str_list_t *input, *sl, *sl1;
  char *s;
  unsigned ok, u, is_mouse, is_joystick;
  unsigned bus, vendor, product, version;
  unsigned mouse_buttons, mouse_wheels;
  char *name = NULL, *handlers = NULL, *key = NULL, *rel = NULL, *abso = NULL;
  size_t len;
  str_list_t *handler_list;
  hd_dev_num_t dev_num = { type: 'c', range: 1 };

  input = read_file("/proc/bus/input/devices", 0, 0);

  ADD2LOG("----- /proc/bus/input/devices -----\n");
  for(sl = input; sl; sl = sl->next) {
    ADD2LOG("  %s", sl->str);
  }
  ADD2LOG("----- /proc/bus/input/devices end -----\n");

  for(ok = 0, sl = input; sl; sl = sl->next) {
    if(*sl->str == '\n') {
      ADD2LOG("bus = %u, name = %s\n", bus, name);
      if(handlers) ADD2LOG("  handlers = %s\n", handlers);
      if(key) ADD2LOG("  key = %s\n", key);
      if(rel) ADD2LOG("  rel = %s\n", rel);
      if(abso) ADD2LOG("  abs = %s\n", abso);

      mouse_buttons = 0;
      if(key) {
        for(u = BTN_MOUSE; u < BTN_MOUSE + 8; u++) {
          if(test_bit(key, u)) mouse_buttons++;
        }
      }
      ADD2LOG("  mouse buttons = %u\n", mouse_buttons);

      mouse_wheels = 0;
      if(rel) {
        for(u = REL_HWHEEL; u <= REL_MAX; u++) {
          if(test_bit(rel, u)) mouse_wheels++;
        }
      }
      ADD2LOG("  mouse wheels = %u\n", mouse_wheels);

      if(ok && handlers) {
        handler_list = hd_split(' ', handlers);

        is_mouse = strstr(handlers, "mouse") ? 1 : 0;
        is_joystick = strstr(handlers, "js") ? 1 : 0;

        if(	// HP Virtual Management Device
          vendor == 0x03f0 &&
          product == 0x1126 &&
          mouse_buttons >= 3
        ) is_mouse = 1;

        ADD2LOG("  is_mouse = %u\n", is_mouse);
        ADD2LOG("  is_joystick = %u\n", is_joystick);

        if(bus == BUS_USB) {
          s = NULL;
          for(sl1 = handler_list; sl1; sl1 = sl1->next) {
            if(sscanf(sl1->str, "mouse%u", &u) == 1) {
              str_printf(&s, 0, "/dev/input/mouse%u", u);
              break;
            }
          }

          if(!s && (is_mouse || is_joystick)) for(sl1 = handler_list; sl1; sl1 = sl1->next) {
            if(sscanf(sl1->str, "event%u", &u) == 1) {
              str_printf(&s, 0, "/dev/input/event%u", u);
              break;
            }
          }

          if(s) {
            for(hd = hd_data->hd; hd; hd = hd->next) {
              if(
                (hd->unix_dev_name2 && !strcmp(hd->unix_dev_name2, s)) ||
                (hd->unix_dev_name && !strcmp(hd->unix_dev_name, s))
              ) {
                if(!hd->base_class.id) {
		  if (is_mouse)
		  {
		    hd->base_class.id = bc_mouse;
		    hd->sub_class.id = sc_mou_usb;
		  }
		  else if (is_joystick)
		  {
		    hd->base_class.id = bc_joystick;
		  }
                }

		if (is_mouse)
		{
		  hd_set_hw_class(hd, hw_mouse);
                  hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210);
                  hd->compat_device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons);
		}
		else if (is_joystick)
		{
		  hd_set_hw_class(hd, hw_joystick);

		  /* add buttons and axis details */
		  add_joystick_details(hd_data, hd, key, abso);
		}

                if(hd->unix_dev_name) add_str_list(&hd->unix_dev_names, hd->unix_dev_name);
                if(hd->unix_dev_name2) add_str_list(&hd->unix_dev_names, hd->unix_dev_name2);

                for(sl1 = handler_list; sl1; sl1 = sl1->next) {
                  if(sscanf(sl1->str, "event%u", &u) == 1) {
                    str_printf(&s, 0, "/dev/input/event%u", u);
                    if(!search_str_list(hd->unix_dev_names, s)) add_str_list(&hd->unix_dev_names, s);
                    s = free_mem(s);
                  }
		  /* add /dev/input/jsN joystick device name */
		  else if (is_joystick)
		  {
		    if(sscanf(sl1->str, "js%u", &u) == 1) {
		      str_printf(&s, 0, "/dev/input/js%u", u);
		      if(!search_str_list(hd->unix_dev_names, s)) add_str_list(&hd->unix_dev_names, s);
		      if(!hd->unix_dev_name2) hd->unix_dev_name2 = new_str(s);
		      s = free_mem(s);
		    }
		  }
                }

                break;
              }
            }
          }

          s = free_mem(s);

        }
        else {
	  // keyboard
          if(search_str_list(handler_list, "kbd") && test_bit(key, KEY_1)) {
            hd = add_hd_entry(hd_data, __LINE__, 0);
            hd->base_class.id = bc_keyboard;
            hd->sub_class.id = sc_keyboard_kbd;
            hd->bus.id = bus_ps2;

            hd->vendor.id = MAKE_ID(0, vendor);
            hd->device.id = MAKE_ID(0, product);
            hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0211);
            hd->compat_device.id = MAKE_ID(TAG_SPECIAL, 0x0001);
            hd->device.name = new_str(name);

            for(sl1 = handler_list; sl1; sl1 = sl1->next) {
              if(sscanf(sl1->str, "event%u", &u) == 1) {
                str_printf(&hd->unix_dev_name, 0, "/dev/input/event%u", u);
                dev_num.major = 13;
                dev_num.minor = 64 + u;
                hd->unix_dev_num = dev_num;
                break;
              }
            }
          }
	  // mouse
          else if(is_mouse) {
            hd = add_hd_entry(hd_data, __LINE__, 0);

            hd->vendor.id = MAKE_ID(0, vendor);
            hd->device.id = MAKE_ID(0, product);

            hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0210);
            hd->compat_device.id = MAKE_ID(TAG_SPECIAL, (mouse_wheels << 4) + mouse_buttons);

            hd->base_class.id = bc_mouse;
            if(bus == BUS_ADB) {
              hd->sub_class.id = sc_mou_bus;
              hd->bus.id = bus_adb;
            }
            else {
              hd->sub_class.id = sc_mou_ps2;
              hd->bus.id = bus_ps2;
            }

            hd->device.name = new_str(name);

#if 0
            /* Synaptics/Alps TouchPad */
            if(
              vendor == 2 &&
              (product == 7 || product == 8) &&
              test_bit(abso, ABS_X) &&
              test_bit(abso, ABS_Y) &&
              test_bit(abso, ABS_PRESSURE) &&
              test_bit(key, BTN_TOOL_FINGER)
            ) {
            }
#endif

            hd->unix_dev_name = new_str(DEV_MICE);
            dev_num.major = 13;
            dev_num.minor = 63;
            hd->unix_dev_num = dev_num;

            for(sl1 = handler_list; sl1; sl1 = sl1->next) {
              if(sscanf(sl1->str, "mouse%u", &u) == 1) {
                str_printf(&hd->unix_dev_name2, 0, "/dev/input/mouse%u", u);
                dev_num.major = 13;
                dev_num.minor = 32 + u;
                hd->unix_dev_num2 = dev_num;
                break;
              }
            }

            add_str_list(&hd->unix_dev_names, hd->unix_dev_name);
            add_str_list(&hd->unix_dev_names, hd->unix_dev_name2);

            for(sl1 = handler_list; sl1; sl1 = sl1->next) {
              if(sscanf(sl1->str, "event%u", &u) == 1) {
                s = NULL;
                str_printf(&s, 0, "/dev/input/event%u", u);
                add_str_list(&hd->unix_dev_names, s);
                s = free_mem(s);
                break;
              }
            }
          }
	  // joystick
          else if(is_joystick) {
            hd = add_hd_entry(hd_data, __LINE__, 0);

            hd->vendor.id = MAKE_ID(0, vendor);
            hd->device.id = MAKE_ID(0, product);

	    hd_set_hw_class(hd, hw_joystick);
            hd->base_class.id = bc_joystick;
            hd->device.name = new_str(name);

	    // gameport? (see <linux/input.h>)
	    if (bus == BUS_GAMEPORT) hd->bus.id = bus_gameport;

	    /* add buttons and axis details */
	    add_joystick_details(hd_data, hd, key, abso);

	    // add eventX device
            for(sl1 = handler_list; sl1; sl1 = sl1->next) {
              if(sscanf(sl1->str, "event%u", &u) == 1) {
                str_printf(&hd->unix_dev_name, 0, "/dev/input/event%u", u);
                dev_num.major = 13;
                dev_num.minor = 64 + u;
                hd->unix_dev_num = dev_num;
                break;
              }
            }

	    // add jsX device
            for(sl1 = handler_list; sl1; sl1 = sl1->next) {
              if(sscanf(sl1->str, "js%u", &u) == 1) {
                str_printf(&hd->unix_dev_name2, 0, "/dev/input/js%u", u);
                break;
              }
            }

            add_str_list(&hd->unix_dev_names, hd->unix_dev_name);
            add_str_list(&hd->unix_dev_names, hd->unix_dev_name2);
	  }
	  else
	  {
	    ADD2LOG("unknown non-USB input device\n");
	  }
        }

        handler_list = free_str_list(handler_list);
      }

      ok = 0;

      name = free_mem(name);
      handlers = free_mem(handlers);
      key = free_mem(key);
      rel = free_mem(rel);
      abso = free_mem(abso);
    }

    if(sscanf(sl->str, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x", &bus, &vendor, &product, &version) == 4) {
      ok = 1;
      continue;
    }

    if(!strncmp(sl->str, INP_NAME, sizeof INP_NAME - 1)) {
      s = sl->str + sizeof INP_NAME;
      len = strlen(s);
      if(len > 2) {
        name = canon_str(s, len - 2);
      }
      continue;
    }

    if(!strncmp(sl->str, INP_HANDLERS, sizeof INP_HANDLERS - 1)) {
      s = sl->str + sizeof INP_HANDLERS - 1;
      handlers = canon_str(s, strlen(s));
      continue;
    }

    if(!strncmp(sl->str, INP_KEY, sizeof INP_KEY - 1)) {
      s = sl->str + sizeof INP_KEY - 1;
      key = canon_str(s, strlen(s));
      key = all_bits(key);
      continue;
    }

    if(!strncmp(sl->str, INP_REL, sizeof INP_REL - 1)) {
      s = sl->str + sizeof INP_REL - 1;
      rel = canon_str(s, strlen(s));
      rel = all_bits(rel);
      continue;
    }

    if(!strncmp(sl->str, INP_ABS, sizeof INP_ABS - 1)) {
      s = sl->str + sizeof INP_ABS - 1;
      abso = canon_str(s, strlen(s));
      abso = all_bits(abso);
      continue;
    }
  }

  free_str_list(input);

}


char *all_bits(char *str)
{
  str_list_t *sl, *sl0;
  char *s = NULL;
  unsigned long u;

  if(!str) return NULL;

  sl = sl0 = hd_split(' ', str);
  for(; sl; sl = sl->next) {
    u = strtoul(sl->str, NULL, 16);
    str_printf(&s, -1, "%0*lx", (int) sizeof (unsigned long) * 2, u);
  }
  free_str_list(sl0);
  free_mem(str);

  return s;
}