示例#1
0
    def category(self):
        if "sys_vendor" in self._attributes:
            return "SYSTEM"

        if "IFINDEX" in self._environment:
            return "NETWORK"

        if "PCI_CLASS" in self._environment:
            pci_class_string = self._environment["PCI_CLASS"]
            pci_class = int(pci_class_string, 16)

            # Strip prog_if if defined
            if pci_class > 0xFFFF:
                pci_class >>= 8

            subclass_id = pci_class & 0xFF
            class_id = (pci_class >> 8) & 0xFF

            if class_id == Pci.BASE_CLASS_NETWORK:
                if subclass_id == Pci.CLASS_NETWORK_WIRELESS:
                    return "WIRELESS"
                else:
                    return "NETWORK"

            if class_id == Pci.BASE_CLASS_DISPLAY:
                return "VIDEO"

            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_USB:
                return "USB"

            if class_id == Pci.BASE_CLASS_STORAGE:
                if subclass_id == Pci.CLASS_STORAGE_SCSI:
                    return "SCSI"

                if subclass_id == Pci.CLASS_STORAGE_IDE:
                    return "IDE"

                if subclass_id == Pci.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"

                if subclass_id == Pci.CLASS_STORAGE_RAID:
                    return "RAID"

            if class_id == Pci.BASE_CLASS_COMMUNICATION \
               and subclass_id == Pci.CLASS_COMMUNICATION_MODEM:
                return "MODEM"

            if class_id == Pci.BASE_CLASS_INPUT \
               and subclass_id == Pci.CLASS_INPUT_SCANNER:
                return "SCANNER"

            if class_id == Pci.BASE_CLASS_MULTIMEDIA:
                if subclass_id == Pci.CLASS_MULTIMEDIA_VIDEO:
                    return "CAPTURE"

                if subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO \
                   or subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO_DEVICE:
                    return "AUDIO"

            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_FIREWIRE:
                return "FIREWIRE"

            if class_id == Pci.BASE_CLASS_BRIDGE \
               and (subclass_id == Pci.CLASS_BRIDGE_PCMCIA \
                    or subclass_id == Pci.CLASS_BRIDGE_CARDBUS):
                return "SOCKET"

        if "bInterfaceClass" in self._attributes:
            interface_class = int(
                self._attributes["bInterfaceClass"], 16)
            interface_subclass = int(
                self._attributes["bInterfaceSubClass"], 16)
            interface_protocol = int(
                self._attributes["bInterfaceProtocol"], 16)

            if interface_class == Usb.BASE_CLASS_AUDIO:
                return "AUDIO"

            if interface_class == Usb.BASE_CLASS_PRINTER:
                return "PRINTER"

            if interface_class == Usb.BASE_CLASS_STORAGE:
                if interface_subclass == Usb.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"

                if interface_subclass == Usb.CLASS_STORAGE_SCSI:
                    return "SCSI"

            if interface_class == Usb.BASE_CLASS_VIDEO:
                return "CAPTURE"

            if interface_class == Usb.BASE_CLASS_WIRELESS:
                if interface_protocol == Usb.PROTOCOL_BLUETOOTH:
                    return "BLUETOOTH"
                else:
                    return "WIRELESS"

        if "ID_TYPE" in self._environment:
            id_type = self._environment["ID_TYPE"]

            if id_type == "cd":
                return "CDROM"

            if id_type == "disk":
                return "DISK"

            if id_type == "video":
                return "VIDEO"

        if "KEY" in self._environment:
            key = self._environment["KEY"].strip("=")
            bitmask = get_bitmask(key)

            for i in range(Input.KEY_Q, Input.KEY_P + 1):
                if not test_bit(i, bitmask):
                    break
            else:
                return "KEYBOARD"

            if test_bit(Input.BTN_TOUCH, bitmask):
                return "TOUCH"

            if test_bit(Input.BTN_MOUSE, bitmask):
                return "MOUSE"

        if "DEVTYPE" in self._environment:
            devtype = self._environment["DEVTYPE"]
            if devtype == "disk":
                if "ID_CDROM" in self._environment:
                    return "CDROM"

                if "ID_DRIVE_FLOPPY" in self._environment:
                    return "FLOPPY"

            if devtype == "scsi_device":
                type = int(self._attributes.get("type", "-1"))
                # Check for FLASH drives, see /lib/udev/rules.d/80-udisks.rules
                if type in (0, 7, 14) \
                   and not any(d.driver == "rts_pstor" for d in self._stack):
                    return "DISK"

                if type == 1:
                    return "TAPE"

                if type == 2:
                    return "PRINTER"

                if type in (4, 5):
                    return "CDROM"

                if type == 6:
                    return "SCANNER"

                if type == 12:
                    return "RAID"

        if "DRIVER" in self._environment:
            if self._environment["DRIVER"] == "floppy":
                return "FLOPPY"

        if self.product:
            return "OTHER"

        return None
示例#2
0
    def category(self):
        if "IFINDEX" in self._environment:
            if "DEVTYPE" in self._environment:
                devtype = self._environment["DEVTYPE"]
                if devtype == "wlan":
                    return "WIRELESS"
            return "NETWORK"

        if self.bus == "sound":
            return "AUDIO"

        if self.bus == "ieee80211":
            return "WIRELESS"

        if "PCI_CLASS" in self._environment:
            pci_class_string = self._environment["PCI_CLASS"]
            pci_class = int(pci_class_string, 16)

            # Strip prog_if if defined
            if pci_class > 0xFFFF:
                pci_class >>= 8

            subclass_id = pci_class & 0xFF
            class_id = (pci_class >> 8) & 0xFF

            if class_id == Pci.BASE_CLASS_NETWORK:
                if subclass_id == Pci.CLASS_NETWORK_WIRELESS:
                    return "WIRELESS"
                else:
                    return "NETWORK"

            if class_id == Pci.BASE_CLASS_DISPLAY:
                if subclass_id == Pci.CLASS_DISPLAY_VGA:
                    return "VIDEO"
                else:
                    return "OTHER"

            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_USB:
                return "USB"

            if class_id == Pci.BASE_CLASS_STORAGE:
                if subclass_id == Pci.CLASS_STORAGE_SCSI:
                    return "SCSI"

                if subclass_id == Pci.CLASS_STORAGE_IDE:
                    return "IDE"

                if subclass_id == Pci.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"

                if subclass_id == Pci.CLASS_STORAGE_RAID:
                    return "RAID"

            if class_id == Pci.BASE_CLASS_COMMUNICATION \
               and subclass_id == Pci.CLASS_COMMUNICATION_MODEM:
                return "MODEM"

            if class_id == Pci.BASE_CLASS_INPUT \
               and subclass_id == Pci.CLASS_INPUT_SCANNER:
                return "SCANNER"

            if class_id == Pci.BASE_CLASS_MULTIMEDIA:
                if subclass_id == Pci.CLASS_MULTIMEDIA_VIDEO:
                    return "CAPTURE"

                if subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO \
                   or subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO_DEVICE:
                    return "AUDIO"

            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_FIREWIRE:
                return "FIREWIRE"

            if class_id == Pci.BASE_CLASS_WIRELESS \
               and subclass_id == Pci.CLASS_WIRELESS_BLUETOOTH:
                return "BLUETOOTH"

            if class_id == Pci.BASE_CLASS_BRIDGE \
               and (subclass_id == Pci.CLASS_BRIDGE_PCMCIA
                    or subclass_id == Pci.CLASS_BRIDGE_CARDBUS):
                return "SOCKET"

        if "TYPE" in self._environment and "INTERFACE" in self._environment:
            interface_class, interface_subclass, interface_protocol = (
                int(i) for i in self._environment["INTERFACE"].split("/"))

            if interface_class == Usb.BASE_CLASS_AUDIO:
                return "AUDIO"

            if interface_class == Usb.BASE_CLASS_PRINTER:
                return "PRINTER"

            if interface_class == Usb.BASE_CLASS_STORAGE:
                if interface_subclass == Usb.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"

                if interface_subclass == Usb.CLASS_STORAGE_SCSI:
                    return "SCSI"

            if interface_class == Usb.BASE_CLASS_VIDEO:
                return "CAPTURE"

            if interface_class == Usb.BASE_CLASS_WIRELESS:
                if interface_protocol == Usb.PROTOCOL_BLUETOOTH:
                    return "BLUETOOTH"
                else:
                    return "WIRELESS"

        if "KEY" in self._environment:
            key = self._environment["KEY"].strip("=")
            bitmask = get_bitmask(key)

            for i in range(Input.KEY_Q, Input.KEY_P + 1):
                if not test_bit(i, bitmask, self._bits):
                    break
            else:
                return "KEYBOARD"

            if test_bit(Input.KEY_CAMERA, bitmask, self._bits):
                # Consider a device with both camera and mouse properties as a
                # KVM hardware device ("keyboard, video and mouse")
                if test_bit(Input.BTN_MOUSE, bitmask, self._bits):
                    return "KVM"
                else:
                    return "CAPTURE"

            if test_bit(Input.BTN_TOUCH, bitmask, self._bits):
                return "TOUCH"

            if test_bit(Input.BTN_MOUSE, bitmask, self._bits):
                return "MOUSE"

        if self.driver:
            if self.driver.startswith("sdhci"):
                return "CARDREADER"

            if self.driver.startswith("mmc"):
                return "CARDREADER"

            if self.driver == "sd" and self.product:
                if any(FLASH_RE.search(k) for k in self._environment.keys()):
                    return "CARDREADER"
                if any(d.bus == 'usb' for d in self._stack):
                    if self.product is not None and CARD_READER_RE.search(self.product):
                        return "CARDREADER"
                    if self.vendor is not None and GENERIC_RE.search(self.vendor):
                        return "CARDREADER"

        if "ID_TYPE" in self._environment:
            id_type = self._environment["ID_TYPE"]

            if id_type == "cd":
                return "CDROM"

            if id_type == "disk":
                return "DISK"

            if id_type == "video":
                return "VIDEO"

        if "RFKILL_TYPE" in self._environment:
            rfkill_type = self._environment["RFKILL_TYPE"]

            if rfkill_type == "bluetooth":
                return "BLUETOOTH"

        if "DEVTYPE" in self._environment:
            devtype = self._environment["DEVTYPE"]
            if devtype == "disk":
                if "ID_CDROM" in self._environment:
                    return "CDROM"

                if "ID_DRIVE_FLOPPY" in self._environment:
                    return "FLOPPY"

            if devtype == "scsi_device":
                match = SCSI_RE.match(self._environment.get("MODALIAS", ""))
                type = int(match.group("type"), 16) if match else -1

                # Check FLASH drives, see /lib/udev/rules.d/80-udisks.rules
                if type in (0, 7, 14) \
                   and not any(d.driver == "rts_pstor" for d in self._stack):
                    return "DISK"

                if type == 1:
                    return "TAPE"

                if type == 2:
                    return "PRINTER"

                if type in (4, 5):
                    return "CDROM"

                if type == 6:
                    return "SCANNER"

                if type == 12:
                    return "RAID"

        if "DRIVER" in self._environment:
            if self._environment["DRIVER"] == "floppy":
                return "FLOPPY"

        if self.product:
            return "OTHER"

        return None
示例#3
0
    def category(self):
        if "IFINDEX" in self._environment:
            if "DEVTYPE" in self._environment:
                devtype = self._environment["DEVTYPE"]
                if devtype == "wlan":
                    return "WIRELESS"
            return "NETWORK"

        if self.bus == "sound":
            return "AUDIO"

        if self.bus == "ieee80211":
            return "WIRELESS"

        if "PCI_CLASS" in self._environment:
            pci_class_string = self._environment["PCI_CLASS"]
            pci_class = int(pci_class_string, 16)

            # Strip prog_if if defined
            if pci_class > 0xFFFF:
                pci_class >>= 8

            subclass_id = pci_class & 0xFF
            class_id = (pci_class >> 8) & 0xFF

            if class_id == Pci.BASE_CLASS_NETWORK:
                if subclass_id == Pci.CLASS_NETWORK_WIRELESS:
                    return "WIRELESS"
                else:
                    return "NETWORK"

            if class_id == Pci.BASE_CLASS_DISPLAY:
                if subclass_id == Pci.CLASS_DISPLAY_VGA:
                    return "VIDEO"
                else:
                    return "OTHER"

            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_USB:
                return "USB"

            if class_id == Pci.BASE_CLASS_STORAGE:
                if subclass_id == Pci.CLASS_STORAGE_SCSI:
                    return "SCSI"

                if subclass_id == Pci.CLASS_STORAGE_IDE:
                    return "IDE"

                if subclass_id == Pci.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"

                if subclass_id == Pci.CLASS_STORAGE_RAID:
                    return "RAID"

            if class_id == Pci.BASE_CLASS_COMMUNICATION \
               and subclass_id == Pci.CLASS_COMMUNICATION_MODEM:
                return "MODEM"

            if class_id == Pci.BASE_CLASS_INPUT \
               and subclass_id == Pci.CLASS_INPUT_SCANNER:
                return "SCANNER"

            if class_id == Pci.BASE_CLASS_MULTIMEDIA:
                if subclass_id == Pci.CLASS_MULTIMEDIA_VIDEO:
                    return "CAPTURE"

                if subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO \
                   or subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO_DEVICE:
                    return "AUDIO"

            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_FIREWIRE:
                return "FIREWIRE"

            if class_id == Pci.BASE_CLASS_WIRELESS \
               and subclass_id == Pci.CLASS_WIRELESS_BLUETOOTH:
                return "BLUETOOTH"

            if class_id == Pci.BASE_CLASS_BRIDGE \
               and (subclass_id == Pci.CLASS_BRIDGE_PCMCIA
                    or subclass_id == Pci.CLASS_BRIDGE_CARDBUS):
                return "SOCKET"

        if "TYPE" in self._environment and "INTERFACE" in self._environment:
            interface_class, interface_subclass, interface_protocol = (
                int(i) for i in self._environment["INTERFACE"].split("/"))

            if interface_class == Usb.BASE_CLASS_AUDIO:
                return "AUDIO"

            if interface_class == Usb.BASE_CLASS_PRINTER:
                return "PRINTER"

            if interface_class == Usb.BASE_CLASS_STORAGE:
                if interface_subclass == Usb.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"

                if interface_subclass == Usb.CLASS_STORAGE_SCSI:
                    return "SCSI"

            if interface_class == Usb.BASE_CLASS_VIDEO:
                return "CAPTURE"

            if interface_class == Usb.BASE_CLASS_WIRELESS:
                if interface_protocol == Usb.PROTOCOL_BLUETOOTH:
                    return "BLUETOOTH"
                else:
                    return "WIRELESS"

        if "KEY" in self._environment:
            key = self._environment["KEY"].strip("=")
            bitmask = get_bitmask(key)

            for i in range(Input.KEY_Q, Input.KEY_P + 1):
                if not test_bit(i, bitmask, self._bits):
                    break
            else:
                return "KEYBOARD"

            if test_bit(Input.KEY_CAMERA, bitmask, self._bits):
                # Consider a device with both camera and mouse properties as a
                # KVM hardware device ("keyboard, video and mouse")
                if test_bit(Input.BTN_MOUSE, bitmask, self._bits):
                    return "KVM"
                else:
                    return "CAPTURE"

            if test_bit(Input.BTN_TOUCH, bitmask, self._bits):
                return "TOUCH"

            if test_bit(Input.BTN_MOUSE, bitmask, self._bits):
                return "MOUSE"

        if self.driver:
            if self.driver.startswith("sdhci"):
                return "CARDREADER"

            if self.driver.startswith("mmc"):
                return "CARDREADER"

            if self.driver == "sd" and self.product:
                if any(FLASH_RE.search(k) for k in self._environment.keys()):
                    return "CARDREADER"
                if any(d.bus == 'usb' for d in self._stack):
                    if self.product is not None and CARD_READER_RE.search(self.product):
                        return "CARDREADER"
                    if self.vendor is not None and GENERIC_RE.search(self.vendor):
                        return "CARDREADER"

        if "ID_TYPE" in self._environment:
            id_type = self._environment["ID_TYPE"]

            if id_type == "cd":
                return "CDROM"

            if id_type == "disk":
                return "DISK"

            if id_type == "video":
                return "VIDEO"

        if "RFKILL_TYPE" in self._environment:
            rfkill_type = self._environment["RFKILL_TYPE"]

            if rfkill_type == "bluetooth":
                return "BLUETOOTH"

        if "DEVTYPE" in self._environment:
            devtype = self._environment["DEVTYPE"]
            if devtype == "disk":
                if "ID_CDROM" in self._environment:
                    return "CDROM"

                if "ID_DRIVE_FLOPPY" in self._environment:
                    return "FLOPPY"

            if devtype == "scsi_device":
                match = SCSI_RE.match(self._environment.get("MODALIAS", ""))
                type = int(match.group("type"), 16) if match else -1

                # Check FLASH drives, see /lib/udev/rules.d/80-udisks.rules
                if type in (0, 7, 14) \
                   and not any(d.driver == "rts_pstor" for d in self._stack):
                    return "DISK"

                if type == 1:
                    return "TAPE"

                if type == 2:
                    return "PRINTER"

                if type in (4, 5):
                    return "CDROM"

                if type == 6:
                    return "SCANNER"

                if type == 12:
                    return "RAID"

        if "DRIVER" in self._environment:
            if self._environment["DRIVER"] == "floppy":
                return "FLOPPY"

        if self.product:
            return "OTHER"

        return None
示例#4
0
    def category(self):
        if "IFINDEX" in self._environment:
            if "DEVTYPE" in self._environment:
                devtype = self._environment["DEVTYPE"]
                if devtype in ("wlan", "wimax"):
                    return "WIRELESS"
            # Ralink wireless
            if "INTERFACE" in self._environment:
                if (
                    self.driver.startswith('rt') and
                    self._environment["INTERFACE"].startswith('ra')
                ):
                    return "WIRELESS"
            return "NETWORK"

        if self.bus == "bluetooth":
            return "BLUETOOTH"

        if "PCI_CLASS" in self._environment:
            pci_class_string = self._environment["PCI_CLASS"]
            pci_class = int(pci_class_string, 16)

            # Strip prog_if if defined
            if pci_class > 0xFFFF:
                pci_class >>= 8

            subclass_id = pci_class & 0xFF
            class_id = (pci_class >> 8) & 0xFF

            if class_id == Pci.BASE_CLASS_NETWORK:
                if subclass_id == Pci.CLASS_NETWORK_WIRELESS:
                    return "WIRELESS"
                else:
                    return "NETWORK"
            if class_id == Pci.BASE_CLASS_DISPLAY:
                if subclass_id == Pci.CLASS_DISPLAY_VGA or subclass_id == Pci.CLASS_DISPLAY_3D:
                    return "VIDEO"
            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_USB:
                return "USB"
            if class_id == Pci.BASE_CLASS_STORAGE:
                if subclass_id == Pci.CLASS_STORAGE_SCSI:
                    return "SCSI"
                if subclass_id == Pci.CLASS_STORAGE_IDE:
                    return "IDE"
                if subclass_id == Pci.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"
                if subclass_id == Pci.CLASS_STORAGE_RAID:
                    return "RAID"
            if class_id == Pci.BASE_CLASS_COMMUNICATION \
               and subclass_id == Pci.CLASS_COMMUNICATION_MODEM:
                return "MODEM"
            if class_id == Pci.BASE_CLASS_INPUT \
               and subclass_id == Pci.CLASS_INPUT_SCANNER:
                return "SCANNER"
            if class_id == Pci.BASE_CLASS_MULTIMEDIA:
                if subclass_id == Pci.CLASS_MULTIMEDIA_VIDEO:
                    return "CAPTURE"
                if subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO \
                   or subclass_id == Pci.CLASS_MULTIMEDIA_AUDIO_DEVICE:
                    return "AUDIO"
            if class_id == Pci.BASE_CLASS_SERIAL \
               and subclass_id == Pci.CLASS_SERIAL_FIREWIRE:
                return "FIREWIRE"
            if class_id == Pci.BASE_CLASS_WIRELESS \
               and subclass_id == Pci.CLASS_WIRELESS_BLUETOOTH:
                return "BLUETOOTH"
            if class_id == Pci.BASE_CLASS_BRIDGE \
               and (subclass_id == Pci.CLASS_BRIDGE_PCMCIA
                    or subclass_id == Pci.CLASS_BRIDGE_CARDBUS):
                return "SOCKET"

        if "TYPE" in self._environment and "INTERFACE" in self._environment:
            interface_class, interface_subclass, interface_protocol = (
                int(i) for i in self._environment["INTERFACE"].split("/"))
            if interface_class == Usb.BASE_CLASS_AUDIO:
                return "AUDIO"
            if interface_class == Usb.BASE_CLASS_PRINTER:
                return "PRINTER"
            if interface_class == Usb.BASE_CLASS_STORAGE:
                if interface_subclass == Usb.CLASS_STORAGE_FLOPPY:
                    return "FLOPPY"
                if interface_subclass == Usb.CLASS_STORAGE_SCSI:
                    return "USB"
            if interface_class == Usb.BASE_CLASS_VIDEO:
                return "CAPTURE"
            if interface_class == Usb.BASE_CLASS_WIRELESS:
                if interface_protocol == Usb.PROTOCOL_BLUETOOTH:
                    return "BLUETOOTH"
                else:
                    return "WIRELESS"
            if (interface_class, interface_subclass, interface_protocol) ==\
               (255, 255, 255) and self.driver == "btusb":
                # This heuristic accounts for bluetooth devices which usually
                # have INTERFACE=224/*/1, however in the "field" we've run
                # across a few (Mediatek combo cards) that have unknown
                # (255/255/255) values and thus break the previous heuristic.
                # We assume that if a device has these weird INTERFACE values
                # *but* it uses the btusb driver, then it must be a bluetooth
                # controller.  Other devices with btusb *but* with
                # INTERFACE=255/1/1 have been seen on systems where the actual
                # usb controller was identified by the old heuristic, so here
                # we need to match all three fields to avoid duplicating
                # devices.  See http://pad.lv/1210405
                    return "BLUETOOTH"

        if 'ID_INPUT_KEYBOARD' in self._environment:
            return "KEYBOARD"
        if 'ID_INPUT_TOUCHPAD' in self._environment:
            return "TOUCHPAD"
        if 'ID_INPUT_TOUCHSCREEN' in self._environment:
            return "TOUCHSCREEN"
        if "ID_INPUT_ACCELEROMETER" in self._environment:
            return "ACCELEROMETER"
        if "KEY" in self._environment:
            key = self._environment["KEY"].strip("=")
            bitmask = get_bitmask(key)
            if test_bit(Input.KEY_CAMERA, bitmask, self._bits):
                # Avoid detecting the power button as a capture device
                if self.vendor_id == 0:
                    return "OTHER"
                # Avoid identifying media/hot keys as pure capture devices
                if not (test_bit(Input.KEY_PLAYPAUSE, bitmask, self._bits) or
                        test_bit(Input.KEY_PLAY, bitmask, self._bits) or
                        test_bit(Input.KEY_WLAN, bitmask, self._bits)):
                    # Consider a device with both camera and mouse properties
                    # as a KVM hardware device ("keyboard, video and mouse")
                    if test_bit(Input.BTN_MOUSE, bitmask, self._bits):
                        return "KVM"
                    else:
                        return "CAPTURE"
        if 'ID_INPUT_MOUSE' in self._environment:
            return "MOUSE"

        if self.driver:
            if self.driver.startswith("sdhci"):
                return "CARDREADER"
            if self.driver.startswith("mmc"):
                return "CARDREADER"
            if self.driver == "rts_pstor":
                return "CARDREADER"
            # See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=702145
            if self.driver.startswith("rtsx"):
                return "CARDREADER"
            if ((self._environment.get("DEVTYPE") not in ("disk", "partition")
                    or 'ID_DRIVE_FLASH_SD' in self._environment)
                    and self.driver == "sd" and self.product):
                if any(FLASH_RE.search(k) for k in self._environment.keys()):
                    return "CARDREADER"
                if any(d.bus == 'usb' for d in self._stack):
                    if (self.product is not None and
                            CARD_READER_RE.search(self.product)):
                        return "CARDREADER"
                    if (self.vendor is not None and
                            GENERIC_RE.search(self.vendor) and
                            not FLASH_DISK_RE.search(self.product)):
                        return "CARDREADER"

        if "ID_TYPE" in self._environment:
            id_type = self._environment["ID_TYPE"]
            if id_type == "cd":
                return "CDROM"
            if (
                id_type == "disk"
                and not any(d.category == "CARDREADER" for d in self._stack)
            ):
                return "DISK"
            if not any(d.bus == 'usb' for d in self._stack):
                if id_type == "video":
                    return "VIDEO"

        if "DEVTYPE" in self._environment:
            devtype = self._environment["DEVTYPE"]
            if devtype == "disk":
                if "ID_CDROM" in self._environment:
                    return "CDROM"
                if "ID_DRIVE_FLOPPY" in self._environment:
                    return "FLOPPY"
            if devtype == "scsi_device":
                match = SCSI_RE.match(self._environment.get("MODALIAS", ""))
                type = int(match.group("type"), 16) if match else -1

                # Check FLASH drives, see /lib/udev/rules.d/80-udisks.rules
                if (
                    type in (0, 7, 14)
                    and not any(d.driver == "rts_pstor" for d in self._stack)
                ):
                    return "DISK"
                if type == 1:
                    return "TAPE"
                if type == 2:
                    return "PRINTER"
                if type in (4, 5):
                    return "CDROM"
                if type == 6:
                    return "SCANNER"
                if type == 12:
                    return "RAID"

        if "DRIVER" in self._environment:
            if self._environment["DRIVER"] == "floppy":
                return "FLOPPY"

        # Some audio and serial devices have a product but no vendor
        # or product id. Special-case their categories for backwards-
        # compatibility.
        if self.bus == "sound":
            return "AUDIO"

        if self.bus == "tty":
            return "OTHER"

        # Any devices that have a product name and proper vendor and product
        # IDs, but had no other category, are lumped together in OTHER.
        # A few devices may have no self.product but carry PRODUCT data in
        # their environment.
        if ((self.product or self._environment.get("PRODUCT")) and
                not None in (self.vendor_id, self.product_id)):
            return "OTHER"

        # Limbo of devices I couldn't otherwise categorize. In practice
        # having no category means the device may be uninteresting, it's
        # up to downstream users of this class to decide what to do with
        # those devices.
        return None