Example #1
0
// An all-in-one function for describing an input device
static PyObject *
ioctl_devinfo(PyObject *self, PyObject *args)
{
    int fd;

    struct input_id iid;
    char name[MAX_NAME_SIZE];
    char phys[MAX_NAME_SIZE] = {0};
    char uniq[MAX_NAME_SIZE] = {0};

    int ret = PyArg_ParseTuple(args, "i", &fd);
    if (!ret) return NULL;

    memset(&iid,  0, sizeof(iid));

    if (ioctl(fd, EVIOCGID, &iid) < 0)                 goto on_err;
    if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) goto on_err;

    // Some devices do not have a physical topology associated with them
    ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys);

    // Some kernels have started reporting bluetooth controller MACs as phys.
    // This lets us get the real physical address. As with phys, it may be blank.
    ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq);

    return Py_BuildValue("hhhhsss", iid.bustype, iid.vendor, iid.product, iid.version,
                         name, phys, uniq);

    on_err:
        PyErr_SetFromErrno(PyExc_IOError);
        return NULL;
}
Example #2
0
static int open_device(const char* device) {
  int version;
  int fd;
  struct pollfd* new_ufds;
  char** new_device_names;
  char name[80];
  char location[80];
  char idstr[80];
  struct input_id id;

  fd = open(device, O_RDWR);
  if (fd < 0) {
    return -1;
  }

  if (ioctl(fd, EVIOCGVERSION, &version)) {
    return -1;
  }
  if (ioctl(fd, EVIOCGID, &id)) {
    return -1;
  }
  name[sizeof(name) - 1] = '\0';
  location[sizeof(location) - 1] = '\0';
  idstr[sizeof(idstr) - 1] = '\0';
  if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
    name[0] = '\0';
  }
  if (ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
    location[0] = '\0';
  }
  if (ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
    idstr[0] = '\0';
  }

  new_ufds = reinterpret_cast<pollfd*>(realloc(ufds, sizeof(ufds[0]) * (nfds + 1)));
  if (new_ufds == NULL) {
    fprintf(stderr, "out of memory\n");
    return -1;
  }
  ufds = new_ufds;
  new_device_names = reinterpret_cast<char**>(realloc(
      device_names, sizeof(device_names[0]) * (nfds + 1)));
  if (new_device_names == NULL) {
    fprintf(stderr, "out of memory\n");
    return -1;
  }
  device_names = new_device_names;
  ufds[nfds].fd = fd;
  ufds[nfds].events = POLLIN;
  device_names[nfds] = strdup(device);
  nfds++;

  return 0;
}
Example #3
0
int SC_LID::getInfo(struct input_id *info, char *bufPhys, size_t sizePhys, char *bufUniq, size_t sizeUniq)
{
	if (ioctl(m_fd, EVIOCGID, info) == -1) {
		error("LID (6): %s\n", strerror(errno));
		return errFailed;
	}
	if (ioctl(m_fd, EVIOCGPHYS(sizePhys), bufPhys) == -1) {
// 		strcpy( sizePhys, strerror(errno));
 		post("LID could not retrieve physical location (error: %s)\n", strerror(errno));
		sprintf(bufPhys, "");
// 		return errFailed;
	}
	if (ioctl(m_fd, EVIOCGUNIQ(sizeUniq), bufUniq) == -1) {
// 		strcpy( strerror(errno), sizeof( strerror(errno)), sizeUniq );
 		post("LID could not get unique identifier (error: %s)\n", strerror(errno));
		sprintf(bufUniq, "");
// 		return errFailed;
	}

	return errNone;
}
Example #4
0
int main(int argc,char* argv[])
{
	
	int fd;
  	int read_num = 0, opt = 0;
  	

	fprintf(stderr,"input device test v0.1\n");
	fprintf(stderr,"This program was compiled at %s %s\n",__DATE__,__TIME__);
	fprintf(stderr,"Author: [email protected]\n");

	   
   while ((opt = getopt(argc, argv, "hr:")) != -1) {
       switch (opt) {
       case 'r':
       		read_num = atoi(optarg);
       		break;
       case 'h':
       default:
           usage(argv[0]);
           return 0;
       }
   }
	
	if (optind >= argc) {
		  usage(argv[0]);
          return -1;
    }
    
	char devpath[256] = "\0";
	if(argv[optind][0] != '/'){
		strcpy(devpath,"/dev/input/");
	}
	strcat(devpath,argv[optind]);
	printf("event driver: %s\n", devpath);

// if((file = open(str, O_RDWR|O_NONBLOCK)) < 0)
	if((fd = open(devpath, O_RDWR)) < 0)
	{
		perror("device can not open");
		return -2;
	}

	
	//Listing 1. Sample EVIOCGVERSION Function
	/* ioctl() accesses the underlying driver */
	int version = 0;
	if (ioctl(fd, EVIOCGVERSION, &version)) {
	    perror("EVIOCGVERSION");
	}
	
	/* the EVIOCGVERSION ioctl() returns an int */
	/* so we unpack it and display it */
	printf("\tversion is %d.%d.%d\n",
	       version >> 16, (version >> 8) & 0xff,
	       version & 0xff);

	
	//Listing 3. Sample EVIOCGID ioctl 
	/* suck out some device information */
	struct input_id device_info;
	if(ioctl(fd, EVIOCGID, &device_info)) {
	    perror("EVIOCGVERSION");
	}
	
	/* the EVIOCGID ioctl() returns input_devinfo
	 * structure - see <linux/input.h>
	 * So we work through the various elements,
	 * displaying each of them
	 */
	printf("\tvendor %04hx product %04hx version %04hx",
	       device_info.vendor, device_info.product,
	       device_info.version);
	switch ( device_info.bustype)
	{
	 case BUS_PCI :
	     printf(" is on a PCI bus\n");
	     break;
	 case BUS_USB :
	     printf(" is on a Universal Serial Bus\n");
	     break;
	 case BUS_I2C :
	     printf(" is on BUS_I2C\n");
	     break;	     
	default:
		printf(" is on an unknow bus %x\n",(unsigned int)device_info.bustype);
		break;	     
	}

	//Listing 4. get name 
	char name[256]= "Unknown";
	if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) {
	    perror("EVIOCGNAME");
	}
	printf("\tname is %s\n", name);
	
	//Listing 5. Using EVIOCGPHYS for Topology Information
	char phys[256]= "\0";
	if(ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0) {
	    //perror("EVIOCGPHYS ");
	}
	printf("\tphys is %s\n", phys);
	
	//Listing 6. Finding a Unique Identifier
	char uniq[256]= "\0";
	if(ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq) < 0) {
	    //perror("EVIOCGUNIQ");
	}
	printf("\tidentity is %s\n",  uniq);
	
	printf("\n");
	//Listing 7. Determining Features with EVIOCGBIT
	unsigned char evtype_b[(EV_MAX >> 3) +1];
	memset(evtype_b, 0, sizeof(evtype_b));
	if (ioctl(fd, EVIOCGBIT(0, EV_MAX), evtype_b) < 0) {
	    perror("EVIOCGBIT");
	}
	
	printf("Supported event types %x:\n",evtype_b[0]);
	int yalv = 0;

	for (yalv = 0; yalv < EV_MAX; yalv++) {
	    if (test_bit(yalv, evtype_b)) {
	        /* the bit is set in the event types list */
	        printf("  Event type 0x%02x ", yalv);
	        switch ( yalv)
	            {
	            case EV_SYN :
	                printf(" (Synch Events)\n");
	                break;
	            case EV_KEY :
	                printf(" (Keys or Buttons)\n");
	                break;
	            case EV_REL :
	                printf(" (Relative Axes)\n");
	                break;
	            case EV_ABS :
	                printf(" (Absolute Axes)\n");
	                break;
	            case EV_MSC :
	                printf(" (Miscellaneous)\n");
	                break;
	            case EV_LED :
	                printf(" (LEDs)\n");
	                break;
	            case EV_SND :
	                printf(" (Sounds)\n");
	                break;
	            case EV_REP :
	                printf(" (Repeat)\n");
	                break;
	            case EV_FF :
	            case EV_FF_STATUS:
	                printf(" (Force Feedback)\n");
	                break;
	            case EV_PWR:
	                printf(" (Power Management)\n");
	                break;
	            default:
	                printf(" (Unknown: 0x%04hx)\n",
	             yalv);
	            }
	    }
	}
	

	
	//Listing 11. Using EVIOCGLED
	unsigned char led_b[64];
	memset(led_b, 0, sizeof(led_b));
	if(ioctl(fd, EVIOCGLED(sizeof(led_b)), led_b)<0){
		perror("EVIOCGLED");
	    return -11;
	}
	
	for (yalv = 0; yalv < LED_MAX; yalv++) {
	    if (test_bit(yalv, led_b)) {
	        /* the bit is set in the LED state */
	        printf("  LED 0x%02x ", yalv);
	        switch ( yalv)
	            {
	            case LED_NUML :
	                printf(" (Num Lock)\n");
	                break;
	            case LED_CAPSL :
	                printf(" (Caps Lock)\n");
	                break;
	            /* other LEDs not shown here*/
	            default:
	                printf(" (Unknown LED: 0x%04hx)\n",
	                       yalv);
	            }
	    }
	}


    printf("\n");
    //Listing 8. Checking for Busy Spots
    /* how many bytes were read */
    size_t rb;
    /* the events (up to 64 at once) */
    struct input_event ev[64];

    while(read_num-- > 0){
        rb=read(fd,ev,sizeof(struct input_event)*64);
        if (rb < (int) sizeof(struct input_event)) {
            perror("evtest: short read");
            return -10;
        }

        for (yalv = 0;
            yalv < (int) (rb / sizeof(struct input_event));
            yalv++)
        {
            printf("%ld.%06ld ",ev[yalv].time.tv_sec,ev[yalv].time.tv_usec);
            printf("type %d code %03d 0x%03x value %d\n",
                ev[yalv].type,
                ev[yalv].code,ev[yalv].code,ev[yalv].value);
         	if (0 == ev[yalv].type) printf("\n");                
        }
        //printf("\n");
    }

	close(fd);
	return 0;
}
Example #5
0
status_t EventHub::openDeviceLocked(const char *devicePath) {
    char buffer[80];

    ALOGV("Opening device: %s", devicePath);

    int fd = open(devicePath, O_RDWR);
    if(fd < 0) {
        LOGE("could not open %s, %s\n", devicePath, strerror(errno));
        return -1;
    }

    InputDeviceIdentifier identifier;

    // Get device name.
    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
        //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.name.setTo(buffer);
    }

    // Check to see if the device is on our excluded list
    for (size_t i = 0; i < mExcludedDevices.size(); i++) {
        const String8& item = mExcludedDevices.itemAt(i);
        if (identifier.name == item) {
            LOGI("ignoring event id %s driver %s\n", devicePath, item.string());
            close(fd);
            return -1;
        }
    }

    // Get device driver version.
    int driverVersion;
    if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
        LOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }

    // Get device identifier.
    struct input_id inputId;
    if(ioctl(fd, EVIOCGID, &inputId)) {
        LOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }
    identifier.bus = inputId.bustype;
    identifier.product = inputId.product;
    identifier.vendor = inputId.vendor;
    identifier.version = inputId.version;

    // Get device physical location.
    if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
        //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.location.setTo(buffer);
    }

    // Get device unique id.
    if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
        //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.uniqueId.setTo(buffer);
    }

    // Make file descriptor non-blocking for use with poll().
    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
        LOGE("Error %d making device file descriptor non-blocking.", errno);
        close(fd);
        return -1;
    }

    // Allocate device.  (The device object takes ownership of the fd at this point.)
    int32_t deviceId = mNextDeviceId++;
    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);

#if 0
    LOGI("add device %d: %s\n", deviceId, devicePath);
    LOGI("  bus:       %04x\n"
         "  vendor     %04x\n"
         "  product    %04x\n"
         "  version    %04x\n",
        identifier.bus, identifier.vendor, identifier.product, identifier.version);
    LOGI("  name:      \"%s\"\n", identifier.name.string());
    LOGI("  location:  \"%s\"\n", identifier.location.string());
    LOGI("  unique id: \"%s\"\n", identifier.uniqueId.string());
    LOGI("  driver:    v%d.%d.%d\n",
        driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
#endif

    // Load the configuration file for the device.
    loadConfigurationLocked(device);

    // Figure out the kinds of events the device reports.
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
    ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
    ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
    ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);

    // See if this is a keyboard.  Ignore everything in the button range except for
    // joystick and gamepad buttons which are handled like keyboards for the most part.
    bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
                    sizeof_bit_array(KEY_MAX + 1));
    bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
                    sizeof_bit_array(BTN_MOUSE))
            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
                    sizeof_bit_array(BTN_DIGI));
    if (haveKeyboardKeys || haveGamepadButtons) {
        device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
    }

    // See if this is a cursor device such as a trackball or mouse.
    if (test_bit(BTN_MOUSE, device->keyBitmask)
            && test_bit(REL_X, device->relBitmask)
            && test_bit(REL_Y, device->relBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_CURSOR;
    }

    // See if this is a touch pad.
    // Is this a new modern multi-touch driver?
    if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
            && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
        // Some joysticks such as the PS3 controller report axes that conflict
        // with the ABS_MT range.  Try to confirm that the device really is
        // a touch screen.
        if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
            device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
        }
    // Is this an old style single-touch driver?
    } else if (test_bit(BTN_TOUCH, device->keyBitmask)
            && test_bit(ABS_X, device->absBitmask)
            && test_bit(ABS_Y, device->absBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_TOUCH;
    }

    // See if this device is a joystick.
    // Assumes that joysticks always have gamepad buttons in order to distinguish them
    // from other devices such as accelerometers that also have absolute axes.
    if (haveGamepadButtons) {
        uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
        for (int i = 0; i <= ABS_MAX; i++) {
            if (test_bit(i, device->absBitmask)
                    && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
                device->classes = assumedClasses;
                break;
            }
        }
    }

    // Check whether this device has switches.
    for (int i = 0; i <= SW_MAX; i++) {
        if (test_bit(i, device->swBitmask)) {
            device->classes |= INPUT_DEVICE_CLASS_SWITCH;
            break;
        }
    }

    // Configure virtual keys.
    if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
        // Load the virtual keys for the touch screen, if any.
        // We do this now so that we can make sure to load the keymap if necessary.
        status_t status = loadVirtualKeyMapLocked(device);
        if (!status) {
            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
        }
    }

    // Load the key map.
    // We need to do this for joysticks too because the key layout may specify axes.
    status_t keyMapStatus = NAME_NOT_FOUND;
    if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
        // Load the keymap for the device.
        keyMapStatus = loadKeyMapLocked(device);
    }

    // Configure the keyboard, gamepad or virtual keyboard.
    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        // Register the keyboard as a built-in keyboard if it is eligible.
        if (!keyMapStatus
                && mBuiltInKeyboardId == -1
                && isEligibleBuiltInKeyboard(device->identifier,
                        device->configuration, &device->keyMap)) {
            mBuiltInKeyboardId = device->id;
        }

        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
        if (hasKeycodeLocked(device, AKEYCODE_Q)) {
            device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
        }

        // See if this device has a DPAD.
        if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
            device->classes |= INPUT_DEVICE_CLASS_DPAD;
        }

        // See if this device has a gamepad.
        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
            if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
                device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
                break;
            }
        }
    }

    // If the device isn't recognized as something we handle, don't monitor it.
    if (device->classes == 0) {
        ALOGV("Dropping device: id=%d, path='%s', name='%s'",
                deviceId, devicePath, device->identifier.name.string());
        delete device;
        return -1;
    }

    // Determine whether the device is external or internal.
    if (isExternalDeviceLocked(device)) {
        device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
    }

    // Register with epoll.
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    eventItem.data.u32 = deviceId;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        LOGE("Could not add device fd to epoll instance.  errno=%d", errno);
        delete device;
        return -1;
    }

    LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
         deviceId, fd, devicePath, device->identifier.name.string(),
         device->classes,
         device->configurationFile.string(),
         device->keyMap.keyLayoutFile.string(),
         device->keyMap.keyCharacterMapFile.string(),
         toString(mBuiltInKeyboardId == deviceId));

    mDevices.add(deviceId, device);

    device->next = mOpeningDevices;
    mOpeningDevices = device;
    return 0;
}
Example #6
0
int
main(void)
{
	TEST_NULL_ARG(EVIOCGVERSION);
	TEST_NULL_ARG(EVIOCGEFFECTS);
	TEST_NULL_ARG(EVIOCGID);
	TEST_NULL_ARG(EVIOCGKEYCODE);
	TEST_NULL_ARG(EVIOCSKEYCODE);
	TEST_NULL_ARG(EVIOCSFF);
# ifdef EVIOCGKEYCODE_V2
	TEST_NULL_ARG(EVIOCGKEYCODE_V2);
# endif
# ifdef EVIOCSKEYCODE_V2
	TEST_NULL_ARG(EVIOCSKEYCODE_V2);
# endif
# ifdef EVIOCGREP
	TEST_NULL_ARG(EVIOCGREP);
# endif
# ifdef EVIOCSREP
	TEST_NULL_ARG(EVIOCSREP);
# endif
# ifdef EVIOCSCLOCKID
	TEST_NULL_ARG(EVIOCSCLOCKID);
# endif

	TEST_NULL_ARG(EVIOCGNAME(0));
	TEST_NULL_ARG(EVIOCGPHYS(0));
	TEST_NULL_ARG(EVIOCGUNIQ(0));
	TEST_NULL_ARG(EVIOCGKEY(0));
	TEST_NULL_ARG(EVIOCGLED(0));
# ifdef EVIOCGMTSLOTS
	TEST_NULL_ARG(EVIOCGMTSLOTS(0));
# endif
# ifdef EVIOCGPROP
	TEST_NULL_ARG(EVIOCGPROP(0));
# endif
	TEST_NULL_ARG(EVIOCGSND(0));
# ifdef EVIOCGSW
	TEST_NULL_ARG(EVIOCGSW(0));
# endif

	TEST_NULL_ARG(EVIOCGABS(ABS_X));
	TEST_NULL_ARG(EVIOCSABS(ABS_X));

	TEST_NULL_ARG(EVIOCGBIT(EV_SYN, 0));
	TEST_NULL_ARG(EVIOCGBIT(EV_KEY, 1));
	TEST_NULL_ARG(EVIOCGBIT(EV_REL, 2));
	TEST_NULL_ARG(EVIOCGBIT(EV_ABS, 3));
	TEST_NULL_ARG(EVIOCGBIT(EV_MSC, 4));
# ifdef EV_SW
	TEST_NULL_ARG(EVIOCGBIT(EV_SW, 5));
# endif
	TEST_NULL_ARG(EVIOCGBIT(EV_LED, 6));
	TEST_NULL_ARG(EVIOCGBIT(EV_SND, 7));
	TEST_NULL_ARG(EVIOCGBIT(EV_REP, 8));
	TEST_NULL_ARG(EVIOCGBIT(EV_FF, 9));
	TEST_NULL_ARG(EVIOCGBIT(EV_PWR, 10));
	TEST_NULL_ARG(EVIOCGBIT(EV_FF_STATUS, 11));

	ioctl(-1, EVIOCGBIT(EV_MAX, 42), 0);
	printf("ioctl(-1, EVIOCGBIT(%#x /* EV_??? */, 42), NULL)"
	       " = -1 EBADF (%m)\n", EV_MAX);

	ioctl(-1, EVIOCRMFF, lmagic);
	printf("ioctl(-1, EVIOCRMFF, %d) = -1 EBADF (%m)\n", (int) lmagic);

	ioctl(-1, EVIOCGRAB, lmagic);
	printf("ioctl(-1, EVIOCGRAB, %lu) = -1 EBADF (%m)\n", lmagic);

# ifdef EVIOCREVOKE
	ioctl(-1, EVIOCREVOKE, lmagic);
	printf("ioctl(-1, EVIOCREVOKE, %lu) = -1 EBADF (%m)\n", lmagic);
# endif

	const unsigned int size = get_page_size();
	void *const page = tail_alloc(size);
	fill_memory(page, size);

	int *const val_int = tail_alloc(sizeof(*val_int));
	*val_int = magic;

# ifdef EVIOCSCLOCKID
	ioctl(-1, EVIOCSCLOCKID, val_int);
	printf("ioctl(-1, EVIOCSCLOCKID, [%u]) = -1 EBADF (%m)\n", *val_int);
# endif

	int *pair_int = tail_alloc(sizeof(*pair_int) * 2);
	pair_int[0] = 0xdeadbeef;
	pair_int[1] = 0xbadc0ded;

# ifdef EVIOSGREP
	ioctl(-1, EVIOCSREP, pair_int);
	printf("ioctl(-1, EVIOCSREP, [%u, %u]) = -1 EBADF (%m)\n",
	       pair_int[0], pair_int[1]);
# endif

	pair_int[1] = 1;
	ioctl(-1, EVIOCSKEYCODE, pair_int);
	printf("ioctl(-1, EVIOCSKEYCODE, [%u, %s]) = -1 EBADF (%m)\n",
	       pair_int[0], "KEY_ESC");

# ifdef EVIOCSKEYCODE_V2
	struct input_keymap_entry *const ike = tail_alloc(sizeof(*ike));
	fill_memory(ike, sizeof(*ike));
	ike->keycode = 2;

	ioctl(-1, EVIOCSKEYCODE_V2, ike);
	printf("ioctl(-1, EVIOCSKEYCODE_V2, {flags=%" PRIu8
	       ", len=%" PRIu8 ", ", ike->flags, ike->len);
#  if VERBOSE
	printf("index=%" PRIu16 ", keycode=%s, scancode=[",
	       ike->index, "KEY_1");
	unsigned int i;
	for (i = 0; i < ARRAY_SIZE(ike->scancode); ++i) {
		if (i > 0)
			printf(", ");
		printf("%" PRIx8, ike->scancode[i]);
	}
	printf("]");
#  else
	printf("...");
#  endif
	errno = EBADF;
	printf("}) = -1 EBADF (%m)\n");
# endif

	struct ff_effect *const ffe = tail_alloc(sizeof(*ffe));
	fill_memory(ffe, sizeof(*ffe));

	ffe->type = FF_CONSTANT;
	ioctl(-1, EVIOCSFF, ffe);
	print_ffe_common(ffe, "FF_CONSTANT");

#  if VERBOSE
	printf(", constant={level=%hd", ffe->u.constant.level);
	print_envelope(&ffe->u.constant.envelope);
	printf("}");
#  else
	printf("...");
#  endif
	errno = EBADF;
	printf("}) = -1 EBADF (%m)\n");

#  if VERBOSE
	ffe->type = FF_RAMP;
	ioctl(-1, EVIOCSFF, ffe);
	print_ffe_common(ffe, "FF_RAMP");
	printf(", ramp={start_level=%hd, end_level=%hd",
	       ffe->u.ramp.start_level, ffe->u.ramp.end_level);
	print_envelope(&ffe->u.ramp.envelope);
	errno = EBADF;
	printf("}}) = -1 EBADF (%m)\n");

	ffe->type = FF_PERIODIC;
	ioctl(-1, EVIOCSFF, ffe);
	print_ffe_common(ffe, "FF_PERIODIC");
	printf(", periodic={waveform=%hu, period=%hu, magnitude=%hd"
	       ", offset=%hd, phase=%hu",
	       ffe->u.periodic.waveform, ffe->u.periodic.period,
	       ffe->u.periodic.magnitude, ffe->u.periodic.offset,
	       ffe->u.periodic.phase);
	print_envelope(&ffe->u.periodic.envelope);
	printf(", custom_len=%u, custom_data=%p}",
	       ffe->u.periodic.custom_len, ffe->u.periodic.custom_data);
	errno = EBADF;
	printf("}) = -1 EBADF (%m)\n");

	ffe->type = FF_RUMBLE;
	ioctl(-1, EVIOCSFF, ffe);
	print_ffe_common(ffe, "FF_RUMBLE");
	printf(", rumble={strong_magnitude=%hu, weak_magnitude=%hu}",
	       ffe->u.rumble.strong_magnitude, ffe->u.rumble.weak_magnitude);
	errno = EBADF;
	printf("}) = -1 EBADF (%m)\n");

	ffe->type = 0xff;
	ioctl(-1, EVIOCSFF, ffe);
	print_ffe_common(ffe, "0xff /* FF_??? */");
	errno = EBADF;
	printf("}) = -1 EBADF (%m)\n");
#  endif

	ioctl(-1, _IOC(_IOC_READ, 0x45, 0x1, 0xff), lmagic);
	printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
	       "_IOC(_IOC_READ, 0x45, 0x1, 0xff)", lmagic);

	ioctl(-1, _IOC(_IOC_WRITE, 0x45, 0x1, 0xff), lmagic);
	printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
	       "_IOC(_IOC_WRITE, 0x45, 0x1, 0xff)", lmagic);

	ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0x45, 0xfe, 0xff), lmagic);
	printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
	       "_IOC(_IOC_READ|_IOC_WRITE, 0x45, 0xfe, 0xff)", lmagic);

	ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0x45, 0, 0), lmagic);
	printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
	       "_IOC(_IOC_READ|_IOC_WRITE, 0x45, 0, 0)", lmagic);

	puts("+++ exited with 0 +++");
	return 0;
}
Example #7
0
static struct orng_device_info *
read_devinfo(struct orng_device_info *devinfo, int with_scancodes, int fd)
{
  int i;
  char buf[1024];
  __u32 sc;
  __u16 j;
  int res = 0;
  __u32 nsc;

  memset(devinfo, 0, sizeof(*devinfo));

  /* device identifier */

  if (ioctl(fd, EVIOCGID, &devinfo->id) < 0) {
    fprintf(stderr, "ioctl(EVIOCGID): %s\n", strerror(errno));
    goto err_ioctl;
  }

  /* event bits */

  if (ioctl(fd, EVIOCGBIT(0, sizeof(devinfo->evbit)), devinfo->evbit) < 0) {
    fprintf(stderr, "ioctl(EVIOCGBIT(0)): %s\n", strerror(errno));
    goto err_ioctl;
  }

  /* keys */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_KEY)) {
    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(devinfo->keybit)), devinfo->keybit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_KEY)): %s\n", strerror(errno));
      goto err_ioctl;
    }

    /* key state */

    if (TEST_ARRAY_BIT(devinfo->evbit, EV_KEY)) {
      if (ioctl(fd, EVIOCGKEY(sizeof(devinfo->key)), devinfo->key) < 0) {
        fprintf(stderr, "ioctl(EVIOCGKEY(%zu)): %s\n",
                sizeof(buf), strerror(errno));
        goto err_ioctl;
      }
    }

    /* read mapping between scan codes and key codes */

    if (with_scancodes) {
      nsc = 1ul<<((CHAR_BIT*sizeof(devinfo->keymap[0][0]))-1);

      for (sc = 0, j = 0; sc < nsc; ++sc) {

        int map[2] = {sc, 0};

        int res = ioctl(fd, EVIOCGKEYCODE, map);

        if (res < 0) {
          if (errno != EINVAL) {
            fprintf(stderr, "ioctl: %s\n", strerror(errno));
            goto err_ioctl;
          }
        } else {
          /* save mapping */

          devinfo->keymap[j][0] = map[0]; /* scan code */
          devinfo->keymap[j][1] = map[1]; /* key code */
          ++j;

          if (j >= sizeof(devinfo->keymap)/sizeof(devinfo->keymap[0])) {
            break;
          }
        }
      }
    }
  }

  /* relative positioning */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_REL)) {
    if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(devinfo->relbit)), devinfo->relbit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_REL)): %s\n", strerror(errno));
      goto err_ioctl;
    }
  }

  /* absolute positioning */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_ABS)) {
    if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(devinfo->absbit)), devinfo->absbit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_ABS)): %s\n", strerror(errno));
      goto err_ioctl;
    }

    /* limits */

    for (i = 0; i <= ABS_MAX; ++i) {
      if (TEST_ARRAY_BIT(devinfo->absbit, i)) {
        if (ioctl(fd, EVIOCGABS(i), devinfo->absinfo+i) < 0) {
          fprintf(stderr, "ioctl(EVIOCGABS(%d)): %s\n", i, strerror(errno));
          goto err_ioctl;
        }
      }
    }
  }

  /* misc */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_MSC)) {
    if (ioctl(fd, EVIOCGBIT(EV_MSC, sizeof(devinfo->mscbit)), devinfo->mscbit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_MSC)): %s\n", strerror(errno));
      goto err_ioctl;
    }
  }

  /* LEDs */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_LED)) {
    if (ioctl(fd, EVIOCGBIT(EV_LED, sizeof(devinfo->ledbit)), devinfo->ledbit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_LED)): %s\n", strerror(errno));
      goto err_ioctl;
    }

    /* LED state */

    if (TEST_ARRAY_BIT(devinfo->evbit, EV_LED)) {
      if (ioctl(fd, EVIOCGLED(sizeof(devinfo->led)), devinfo->led) < 0) {
        fprintf(stderr, "ioctl(EVIOCGLED(%zu)): %s\n",
                sizeof(buf), strerror(errno));
        goto err_ioctl;
      }
    }
  }

  /* sound */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_SND)) {
    if (ioctl(fd, EVIOCGBIT(EV_SND, sizeof(devinfo->sndbit)), devinfo->sndbit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_SND)): %s\n", strerror(errno));
      goto err_ioctl;
    }

    /* sound state */

    if (TEST_ARRAY_BIT(devinfo->evbit, EV_SW)) {
      if (ioctl(fd, EVIOCGSND(sizeof(devinfo->snd)), devinfo->snd) < 0) {
        fprintf(stderr, "ioctl(EVIOCGSND(%zu)): %s\n",
                sizeof(buf), strerror(errno));
        goto err_ioctl;
      }
    }
  }

  /* force feedback */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_FF)) {
    if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(devinfo->ffbit)), devinfo->ffbit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_FF)): %s\n", strerror(errno));
      goto err_ioctl;
    }
  }

  /* switches */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_SW)) {
    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(devinfo->swbit)), devinfo->swbit) < 0) {
      fprintf(stderr, "ioctl(EVIOCGBIT(EV_SW)): %s\n", strerror(errno));
      goto err_ioctl;
    }

    /* switch state */

    if (TEST_ARRAY_BIT(devinfo->evbit, EV_SW)) {
      if (ioctl(fd, EVIOCGSW(sizeof(devinfo->sw)), devinfo->sw) < 0) {
        fprintf(stderr, "ioctl(EVIOCGSW(%zu)): %s\n",
                sizeof(buf), strerror(errno));
        goto err_ioctl;
      }
    }
  }

  /* auto repeat */

  if (TEST_ARRAY_BIT(devinfo->evbit, EV_REP)) {
    if (ioctl(fd, EVIOCGREP, devinfo->rep) < 0) {
      fprintf(stderr, "ioctl(EVIOCGREP): %s\n", strerror(errno));
      goto err_ioctl;
    }
  }

  /* name */

  memset(buf, 0, sizeof(buf));

  do {
    res = ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
  } while ((res < 0) && (errno == EINTR));

  if (res >= 0) {
    devinfo->name = strndup(buf, sizeof(buf)-1);

    if (!devinfo->name) {
      fprintf(stderr, "strdup: %s\n", strerror(errno));
      goto err_strdup_name;
    }
  } else if (errno != ENOENT) {
    fprintf(stderr, "ioctl(EVIOCGPHYS(%lu)): %s\n",
            (unsigned long)sizeof(buf), strerror(errno));
    goto err_ioctl;
  }

  /* physical location */

  memset(buf, 0, sizeof(buf));

  do {
    res = ioctl(fd, EVIOCGPHYS(sizeof(buf)), buf);
  } while ((res < 0) && (errno == EINTR));

  if (res >= 0) {
    devinfo->phys = strndup(buf, sizeof(buf)-1);

    if (!devinfo->phys) {
      fprintf(stderr, "strdup: %s\n", strerror(errno));
      goto err_strdup_phys;
    }
  } else if (errno != ENOENT) {
    fprintf(stderr, "ioctl(EVIOCGPHYS(%lu)): %s\n",
            (unsigned long)sizeof(buf), strerror(errno));
    goto err_ioctl;
  }

  /* unique identifier */

  memset(buf, 0, sizeof(buf));

  do {
    res = ioctl(fd, EVIOCGUNIQ(sizeof(buf)), buf);
  } while ((res < 0) && (errno == EINTR));

  if (res >= 0) {
    devinfo->uniq = strndup(buf, sizeof(buf)-1);

    if (!devinfo->uniq) {
      fprintf(stderr, "strdup: %s\n", strerror(errno));
      goto err_strdup_uniq;
    }
  } else if (errno != ENOENT) {
    fprintf(stderr, "ioctl(EVIOCGUNIQ(%lu)): %s\n",
            (unsigned long)sizeof(buf), strerror(errno));
    goto err_ioctl;
  }

  return devinfo;

err_strdup_uniq:
  free(devinfo->phys);
err_strdup_phys:
err_ioctl_gphys:
  free(devinfo->name);
err_strdup_name:
err_ioctl:
  return NULL;
}
Example #8
0
int EventHub::open_device(const char *deviceName)
{
    int version;
    int fd;
    struct pollfd *new_mFDs;
    device_t **new_devices;
    char **new_device_names;
    char name[80];
    char location[80];
    char idstr[80];
    struct input_id id;

    LOGV("Opening device: %s", deviceName);

    AutoMutex _l(mLock);

    fd = open(deviceName, O_RDWR);
    if(fd < 0) {
        LOGE("could not open %s, %s\n", deviceName, strerror(errno));
        return -1;
    }

    if(ioctl(fd, EVIOCGVERSION, &version)) {
        LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
        return -1;
    }
    if(ioctl(fd, EVIOCGID, &id)) {
        LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
        return -1;
    }
    name[sizeof(name) - 1] = '\0';
    location[sizeof(location) - 1] = '\0';
    idstr[sizeof(idstr) - 1] = '\0';
    if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
        //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
        name[0] = '\0';
    }

    // check to see if the device is on our excluded list
    List<String8>::iterator iter = mExcludedDevices.begin();
    List<String8>::iterator end = mExcludedDevices.end();
    for ( ; iter != end; iter++) {
        const char* test = *iter;
        if (strcmp(name, test) == 0) {
            LOGI("ignoring event id %s driver %s\n", deviceName, test);
            close(fd);
            return -1;
        }
    }

    if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
        //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
        location[0] = '\0';
    }
    if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
        //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
        idstr[0] = '\0';
    }

    int devid = 0;
    while (devid < mNumDevicesById) {
        if (mDevicesById[devid].device == NULL) {
            break;
        }
        devid++;
    }
    if (devid >= mNumDevicesById) {
        device_ent* new_devids = (device_ent*)realloc(mDevicesById,
                sizeof(mDevicesById[0]) * (devid + 1));
        if (new_devids == NULL) {
            LOGE("out of memory");
            return -1;
        }
        mDevicesById = new_devids;
        mNumDevicesById = devid+1;
        mDevicesById[devid].device = NULL;
        mDevicesById[devid].seq = 0;
    }

    mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
    if (mDevicesById[devid].seq == 0) {
        mDevicesById[devid].seq = 1<<SEQ_SHIFT;
    }

    new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
    new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
    if (new_mFDs == NULL || new_devices == NULL) {
        LOGE("out of memory");
        return -1;
    }
    mFDs = new_mFDs;
    mDevices = new_devices;

#if 0
    LOGI("add device %d: %s\n", mFDCount, deviceName);
    LOGI("  bus:      %04x\n"
         "  vendor    %04x\n"
         "  product   %04x\n"
         "  version   %04x\n",
        id.bustype, id.vendor, id.product, id.version);
    LOGI("  name:     \"%s\"\n", name);
    LOGI("  location: \"%s\"\n"
         "  id:       \"%s\"\n", location, idstr);
    LOGI("  version:  %d.%d.%d\n",
        version >> 16, (version >> 8) & 0xff, version & 0xff);
#endif

    device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
    if (device == NULL) {
        LOGE("out of memory");
        return -1;
    }

    mFDs[mFDCount].fd = fd;
    mFDs[mFDCount].events = POLLIN;

    // figure out the kinds of events the device reports
    
    // See if this is a keyboard, and classify it.  Note that we only
    // consider up through the function keys; we don't want to include
    // ones after that (play cd etc) so we don't mistakenly consider a
    // controller to be a keyboard.
    uint8_t key_bitmask[(KEY_MAX+7)/8];
    memset(key_bitmask, 0, sizeof(key_bitmask));
    LOGV("Getting keys...");
    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
        //LOGI("MAP\n");
        //for (int i=0; i<((KEY_MAX+7)/8); i++) {
        //    LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
        //}
        for (int i=0; i<((BTN_MISC+7)/8); i++) {
            if (key_bitmask[i] != 0) {
                device->classes |= CLASS_KEYBOARD;
                break;
            }
        }
        if ((device->classes & CLASS_KEYBOARD) != 0) {
            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
            if (device->keyBitmask != NULL) {
                memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
            } else {
                delete device;
                LOGE("out of memory allocating key bitmask");
                return -1;
            }
        }
    }
    
    // See if this is a trackball.
    if (test_bit(BTN_MOUSE, key_bitmask)) {
        uint8_t rel_bitmask[(REL_MAX+7)/8];
        memset(rel_bitmask, 0, sizeof(rel_bitmask));
        LOGV("Getting relative controllers...");
        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
        {
            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
                if (test_bit(BTN_LEFT, key_bitmask) && test_bit(BTN_RIGHT, key_bitmask))
                    device->classes |= CLASS_MOUSE;
                else
                    device->classes |= CLASS_TRACKBALL;
            }
        }
    }
    
    uint8_t abs_bitmask[(ABS_MAX+7)/8];
    memset(abs_bitmask, 0, sizeof(abs_bitmask));
    LOGV("Getting absolute controllers...");
    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
    
    // Is this a new modern multi-touch driver?
    if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
            && test_bit(ABS_MT_POSITION_X, abs_bitmask)
            && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
        device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;
        
    // Is this an old style single-touch driver?
    } else if (test_bit(BTN_TOUCH, key_bitmask)
            && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
        device->classes |= CLASS_TOUCHSCREEN;
#ifdef HAVE_TSLIB
                mTS->fd = fd;

                //Configure here
                LOGV("Device name = %s, fd = %d", deviceName,fd);
                LOGV("tslib: calling ts_config from eventhub\n");
                if(ts_config(mTS)) {
                    LOGE("Error in Configuring tslib. Device Name = %s \n", deviceName);
                }
#endif
    }

#ifdef EV_SW
    // figure out the switches this device reports
    uint8_t sw_bitmask[(SW_MAX+7)/8];
    memset(sw_bitmask, 0, sizeof(sw_bitmask));
    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
        for (int i=0; i<EV_SW; i++) {
            //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
            if (test_bit(i, sw_bitmask)) {
                if (mSwitches[i] == 0) {
                    mSwitches[i] = device->id;
                }
            }
        }
    }
#endif

    if ((device->classes&CLASS_KEYBOARD) != 0) {
        char tmpfn[sizeof(name)];
        char keylayoutFilename[300];

        // a more descriptive name
        device->name = name;

        // replace all the spaces with underscores
        strcpy(tmpfn, name);
        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
            *p = '_';

        // find the .kl file we need for this device
        const char* root = getenv("ANDROID_ROOT");
        snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                 "%s/usr/keylayout/%s.kl", root, tmpfn);
        bool defaultKeymap = false;
        if (access(keylayoutFilename, R_OK)) {
            snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                     "%s/usr/keylayout/%s", root, "qwerty.kl");
            defaultKeymap = true;
        }
        device->layoutMap->load(keylayoutFilename);

        // tell the world about the devname (the descriptive name)
        if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
            // the built-in keyboard has a well-known device ID of 0,
            // this device better not go away.
            mHaveFirstKeyboard = true;
            mFirstKeyboardId = device->id;
            property_set("hw.keyboards.0.devname", name);
        } else {
            // ensure mFirstKeyboardId is set to -something-.
            if (mFirstKeyboardId == 0) {
                mFirstKeyboardId = device->id;
            }
        }
        char propName[100];
        sprintf(propName, "hw.keyboards.%u.devname", device->id);
        property_set(propName, name);

        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
        if (hasKeycode(device, kKeyCodeQ)) {
            device->classes |= CLASS_ALPHAKEY;
        }
        
        // See if this has a DPAD.
        if (hasKeycode(device, kKeyCodeDpadUp) &&
                hasKeycode(device, kKeyCodeDpadDown) &&
                hasKeycode(device, kKeyCodeDpadLeft) &&
                hasKeycode(device, kKeyCodeDpadRight) &&
                hasKeycode(device, kKeyCodeDpadCenter)) {
            device->classes |= CLASS_DPAD;
        }
        
        LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
                device->id, name, propName, keylayoutFilename);
    }

    // If the device isn't recognized as something we handle, don't monitor it.
    if (device->classes == 0) {
        LOGV("Dropping device %s %p, id = %d\n", deviceName, device, devid);
        close(fd);
        delete device;
        return -1;
    }

    LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
         deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
         
    LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
         deviceName, device, mFDCount, devid, device->classes);

    mDevicesById[devid].device = device;
    device->next = mOpeningDevices;
    mOpeningDevices = device;
    mDevices[mFDCount] = device;

    mFDCount++;
    return 0;
}
Example #9
0
static void input_sanitise(const struct ioctl_group *grp, int childno)
{
	unsigned int u, r;

	pick_random_ioctl(grp, childno);

	switch (shm->syscall[childno].a2) {
	case EVIOCGNAME(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGNAME(u);
		break;
	case EVIOCGPHYS(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGPHYS(u);
		break;
	case EVIOCGUNIQ(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGUNIQ(u);
		break;
#ifdef EVIOCGPROP
	case EVIOCGPROP(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGPROP(u);
		break;
#endif
#ifdef EVIOCGMTSLOTS
	case EVIOCGMTSLOTS(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGMTSLOTS(u);
		break;
#endif
	case EVIOCGKEY(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGKEY(u);
		break;
	case EVIOCGLED(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGLED(u);
		break;
	case EVIOCGSND(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGSND(u);
		break;
	case EVIOCGSW(0):
		u = rand();
		shm->syscall[childno].a2 = EVIOCGSW(u);
		break;
	case EVIOCGBIT(0,0):
		u = rand();
		r = rand();
		if (u % 10) u %= EV_CNT;
		if (r % 10) r /= 4;
		shm->syscall[childno].a2 = EVIOCGBIT(u, r);
		break;
	case EVIOCGABS(0):
		u = rand();
		if (u % 10) u %= ABS_CNT;
		shm->syscall[childno].a2 = EVIOCGABS(u);
		break;
	case EVIOCSABS(0):
		u = rand();
		if (u % 10) u %= ABS_CNT;
		shm->syscall[childno].a2 = EVIOCSABS(u);
		break;
	default:
		break;
	}
}
Example #10
0
static const struct ioctl input_ioctls[] = {
	IOCTL(EVIOCGVERSION),
	IOCTL(EVIOCGID),
	IOCTL(EVIOCGREP),
	IOCTL(EVIOCSREP),
	IOCTL(EVIOCGKEYCODE),
#ifdef EVIOCGKEYCODE_V2
	IOCTL(EVIOCGKEYCODE_V2),
#endif
	IOCTL(EVIOCSKEYCODE),
#ifdef EVIOCSKEYCODE_V2
	IOCTL(EVIOCSKEYCODE_V2),
#endif
	IOCTL(EVIOCGNAME(0)),
	IOCTL(EVIOCGPHYS(0)),
	IOCTL(EVIOCGUNIQ(0)),
#ifdef EVIOCGPROP
	IOCTL(EVIOCGPROP(0)),
#endif
#ifdef EVIOCGMTSLOTS
	IOCTL(EVIOCGMTSLOTS(0)),
#endif
	IOCTL(EVIOCGKEY(0)),
	IOCTL(EVIOCGLED(0)),
	IOCTL(EVIOCGSND(0)),
	IOCTL(EVIOCGSW(0)),
	IOCTL(EVIOCGBIT(0,0)),
	IOCTL(EVIOCGABS(0)),
	IOCTL(EVIOCSABS(0)),
	IOCTL(EVIOCSFF),
	IOCTL(EVIOCRMFF),
		/*
		 * It so happens that the pointer that gives us the trouble
		 * is the last field in the structure. Since we don't support
		 * custom waveforms in uinput anyway we can just copy the whole
		 * thing (to the compat size) and ignore the pointer.
		 */
		memcpy(&ff_up_compat.effect, &ff_up->effect,
			sizeof(struct ff_effect_compat));
		memcpy(&ff_up_compat.old, &ff_up->old,
			sizeof(struct ff_effect_compat));

		if (copy_to_user(buffer, &ff_up_compat,
				 sizeof(struct uinput_ff_upload_compat)))
			return -EFAULT;
	} else {
		if (copy_to_user(buffer, ff_up,
				 sizeof(struct uinput_ff_upload)))
			return -EFAULT;
	}

	return 0;
}

static int uinput_ff_upload_from_user(const char __user *buffer,
				      struct uinput_ff_upload *ff_up)
{
	if (INPUT_COMPAT_TEST) {
		struct uinput_ff_upload_compat ff_up_compat;

		if (copy_from_user(&ff_up_compat, buffer,
				   sizeof(struct uinput_ff_upload_compat)))
			return -EFAULT;

		ff_up->request_id = ff_up_compat.request_id;
		ff_up->retval = ff_up_compat.retval;
		memcpy(&ff_up->effect, &ff_up_compat.effect,
			sizeof(struct ff_effect_compat));
		memcpy(&ff_up->old, &ff_up_compat.old,
			sizeof(struct ff_effect_compat));

	} else {
		if (copy_from_user(ff_up, buffer,
				   sizeof(struct uinput_ff_upload)))
			return -EFAULT;
	}

	return 0;
}

#else

static int uinput_ff_upload_to_user(char __user *buffer,
				    const struct uinput_ff_upload *ff_up)
{
	if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload)))
		return -EFAULT;

	return 0;
}

static int uinput_ff_upload_from_user(const char __user *buffer,
				      struct uinput_ff_upload *ff_up)
{
	if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload)))
		return -EFAULT;

	return 0;
}

#endif

#define uinput_set_bit(_arg, _bit, _max)		\
({							\
	int __ret = 0;					\
	if (udev->state == UIST_CREATED)		\
		__ret =  -EINVAL;			\
	else if ((_arg) > (_max))			\
		__ret = -EINVAL;			\
	else set_bit((_arg), udev->dev->_bit);		\
	__ret;						\
})

#ifdef CONFIG_FEATURE_PANTECH_MDS_MTC //|| defined(FEATURE_PANTECH_STABILITY)
#ifdef CONFIG_COMPAT 
#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
#define BITS_TO_LONGS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
#ifdef __BIG_ENDIAN
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
       unsigned int maxlen, void __user *p, int compat)
{
   int len, i;
   if (compat) {
     len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t);
     if (len > maxlen)
       len = maxlen;
     for (i = 0; i < len / sizeof(compat_long_t); i++)
       if (copy_to_user((compat_long_t __user *) p + i,
            (compat_long_t *) bits +
             i + 1 - ((i % 2) << 1),
            sizeof(compat_long_t)))
         return -EFAULT;
   } else {
     len = BITS_TO_LONGS(maxbit) * sizeof(long);
     if (len > maxlen)
       len = maxlen;
     if (copy_to_user(p, bits, len))
       return -EFAULT;
   }
   return len;
}
#else
 static int bits_to_user(unsigned long *bits, unsigned int maxbit,
      unsigned int maxlen, void __user *p, int compat)
{
  int len = compat ?
      BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t) :
      BITS_TO_LONGS(maxbit) * sizeof(long);
  if (len > maxlen)
    len = maxlen;
  return copy_to_user(p, bits, len) ? -EFAULT : len;
}
#endif /* __BIG_ENDIAN */
#else
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
      unsigned int maxlen, void __user *p, int compat)
{
  int len = BITS_TO_LONGS(maxbit) * sizeof(long);
  if (len > maxlen)
    len = maxlen;
  return copy_to_user(p, bits, len) ? -EFAULT : len;
}
#endif /* CONFIG_COMPAT */
static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
{
  int len;
  if (!str)
    return -ENOENT;
  len = strlen(str) + 1;
  if (len > maxlen)
    len = maxlen;
  return copy_to_user(p, str, len) ? -EFAULT : len;
}
#define OLD_KEY_MAX 0x1ff
static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) 
{
  unsigned long *bits;
  int len;
  switch (_IOC_NR(cmd) & EV_MAX) {
   case      0: bits = dev->evbit;  len = EV_MAX;  break;
   case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
   case EV_REL: bits = dev->relbit; len = REL_MAX; break;
   case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
   case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
   case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
   case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
   case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
   case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
   default: return -EINVAL;
  }
  if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) {
     len = OLD_KEY_MAX;
  }
   return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
}
#undef OLD_KEY_MAX
#endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/
static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
				 unsigned long arg, void __user *p)
{
	int			retval;
	struct uinput_device	*udev = file->private_data;
	struct uinput_ff_upload ff_up;
	struct uinput_ff_erase  ff_erase;
	struct uinput_request   *req;
	char			*phys;

	retval = mutex_lock_interruptible(&udev->mutex);
	if (retval)
		return retval;

	if (!udev->dev) {
		retval = uinput_allocate_device(udev);
		if (retval)
			goto out;
	}

	switch (cmd) {
		case UI_DEV_CREATE:
			retval = uinput_create_device(udev);
			break;

		case UI_DEV_DESTROY:
			uinput_destroy_device(udev);
			break;
#ifdef CONFIG_FEATURE_PANTECH_MDS_MTC //|| defined(FEATURE_PANTECH_STABILITY)
   case EVIOCGVERSION: 
		 if (udev->state != UIST_CREATED) 
			retval = -ENODEV;	
		 else put_user(EV_VERSION, (int __user *)p);
		  break;
	 case EVIOCGID:
		 if (udev->state != UIST_CREATED) 
			retval = -ENODEV;	
	   else if (copy_to_user(p, &udev->dev->id, sizeof(struct input_id)))
			retval = -EFAULT;
			break; 
#endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/	 

		case UI_SET_EVBIT:
			retval = uinput_set_bit(arg, evbit, EV_MAX);
			break;

		case UI_SET_KEYBIT:
			retval = uinput_set_bit(arg, keybit, KEY_MAX);
			break;

		case UI_SET_RELBIT:
			retval = uinput_set_bit(arg, relbit, REL_MAX);
			break;

		case UI_SET_ABSBIT:
			retval = uinput_set_bit(arg, absbit, ABS_MAX);
			break;

		case UI_SET_MSCBIT:
			retval = uinput_set_bit(arg, mscbit, MSC_MAX);
			break;

		case UI_SET_LEDBIT:
			retval = uinput_set_bit(arg, ledbit, LED_MAX);
			break;

		case UI_SET_SNDBIT:
			retval = uinput_set_bit(arg, sndbit, SND_MAX);
			break;

		case UI_SET_FFBIT:
			retval = uinput_set_bit(arg, ffbit, FF_MAX);
			break;

		case UI_SET_SWBIT:
			retval = uinput_set_bit(arg, swbit, SW_MAX);
			break;

		case UI_SET_PROPBIT:
			retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
			break;

		case UI_SET_PHYS:
			if (udev->state == UIST_CREATED) {
				retval = -EINVAL;
				goto out;
			}

			phys = strndup_user(p, 1024);
			if (IS_ERR(phys)) {
				retval = PTR_ERR(phys);
				goto out;
			}

			kfree(udev->dev->phys);
			udev->dev->phys = phys;
			break;

		case UI_BEGIN_FF_UPLOAD:
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
				break;

			req = uinput_request_find(udev, ff_up.request_id);
			if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) {
				retval = -EINVAL;
				break;
			}

			ff_up.retval = 0;
			ff_up.effect = *req->u.upload.effect;
			if (req->u.upload.old)
				ff_up.old = *req->u.upload.old;
			else
				memset(&ff_up.old, 0, sizeof(struct ff_effect));

			retval = uinput_ff_upload_to_user(p, &ff_up);
			break;

		case UI_BEGIN_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			req = uinput_request_find(udev, ff_erase.request_id);
			if (!req || req->code != UI_FF_ERASE) {
				retval = -EINVAL;
				break;
			}

			ff_erase.retval = 0;
			ff_erase.effect_id = req->u.effect_id;
			if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			break;

		case UI_END_FF_UPLOAD:
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
				break;

			req = uinput_request_find(udev, ff_up.request_id);
			if (!req || req->code != UI_FF_UPLOAD ||
			    !req->u.upload.effect) {
				retval = -EINVAL;
				break;
			}

			req->retval = ff_up.retval;
			uinput_request_done(udev, req);
			break;

		case UI_END_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			req = uinput_request_find(udev, ff_erase.request_id);
			if (!req || req->code != UI_FF_ERASE) {
				retval = -EINVAL;
				break;
			}

			req->retval = ff_erase.retval;
			uinput_request_done(udev, req);
			break;

		default:
#ifdef CONFIG_FEATURE_PANTECH_MDS_MTC // || defined(FEATURE_PANTECH_STABILITY)
		{
			 if (udev->state != UIST_CREATED){ 
				retval = -ENODEV;	
				break;
			 }
			 if (_IOC_DIR(cmd) == _IOC_READ) { 
				if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
				  handle_eviocgbit(udev->dev, cmd, p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
				  bits_to_user(udev->dev->key, KEY_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
				  bits_to_user(udev->dev->led, LED_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
				  bits_to_user(udev->dev->snd, SND_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
				  bits_to_user(udev->dev->sw, SW_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
				  str_to_user(udev->dev->name, _IOC_SIZE(cmd), p);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
				  str_to_user(udev->dev->phys, _IOC_SIZE(cmd), p);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
				  str_to_user(udev->dev->uniq, _IOC_SIZE(cmd), p);
				if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
			      int t;
			      struct input_absinfo abs;
			      t = _IOC_NR(cmd) & ABS_MAX;
						abs.value = input_abs_get_val(udev->dev,t);
						abs.minimum = input_abs_get_min(udev->dev,t);
				    abs.maximum = input_abs_get_max(udev->dev,t);
				    abs.fuzz = input_abs_get_fuzz(udev->dev,t);
				    abs.flat = input_abs_get_flat(udev->dev,t);
				/*
			      abs.value = udev->dev->abs[t];
				    abs.minimum = udev->dev->absmin[t];
				    abs.maximum = udev->dev->absmax[t];
				    abs.fuzz = udev->dev->absfuzz[t];
				    abs.flat = udev->dev->absflat[t];

				*/
						if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
						 retval= -EFAULT;
				  }
			}
		}
#else
			retval = -EINVAL;
#endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/
	}

 out:
	mutex_unlock(&udev->mutex);
	return retval;
}
int EventHub::openDevice(const char *deviceName) {
    int version;
    int fd;
    struct pollfd *new_mFDs;
    device_t **new_devices;
    char **new_device_names;
    char name[80];
    char location[80];
    char idstr[80];
    struct input_id id;

    LOGV("Opening device: %s", deviceName);

    AutoMutex _l(mLock);

    fd = open(deviceName, O_RDWR);
    if(fd < 0) {
        LOGE("could not open %s, %s\n", deviceName, strerror(errno));
        return -1;
    }

    if(ioctl(fd, EVIOCGVERSION, &version)) {
        LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
        return -1;
    }
    if(ioctl(fd, EVIOCGID, &id)) {
        LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
        return -1;
    }
    name[sizeof(name) - 1] = '\0';
    location[sizeof(location) - 1] = '\0';
    idstr[sizeof(idstr) - 1] = '\0';
    if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
        //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
        name[0] = '\0';
    }

    // check to see if the device is on our excluded list
    List<String8>::iterator iter = mExcludedDevices.begin();
    List<String8>::iterator end = mExcludedDevices.end();
    for ( ; iter != end; iter++) {
        const char* test = *iter;
        if (strcmp(name, test) == 0) {
            LOGI("ignoring event id %s driver %s\n", deviceName, test);
            close(fd);
            return -1;
        }
    }

    if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
        //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
        location[0] = '\0';
    }
    if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
        //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
        idstr[0] = '\0';
    }

    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
        LOGE("Error %d making device file descriptor non-blocking.", errno);
        close(fd);
        return -1;
    }

    int devid = 0;
    while (devid < mNumDevicesById) {
        if (mDevicesById[devid].device == NULL) {
            break;
        }
        devid++;
    }
    if (devid >= mNumDevicesById) {
        device_ent* new_devids = (device_ent*)realloc(mDevicesById,
                sizeof(mDevicesById[0]) * (devid + 1));
        if (new_devids == NULL) {
            LOGE("out of memory");
            return -1;
        }
        mDevicesById = new_devids;
        mNumDevicesById = devid+1;
        mDevicesById[devid].device = NULL;
        mDevicesById[devid].seq = 0;
    }

    mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
    if (mDevicesById[devid].seq == 0) {
        mDevicesById[devid].seq = 1<<SEQ_SHIFT;
    }

    new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
    new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
    if (new_mFDs == NULL || new_devices == NULL) {
        LOGE("out of memory");
        return -1;
    }
    mFDs = new_mFDs;
    mDevices = new_devices;

#if 0
    LOGI("add device %d: %s\n", mFDCount, deviceName);
    LOGI("  bus:      %04x\n"
         "  vendor    %04x\n"
         "  product   %04x\n"
         "  version   %04x\n",
        id.bustype, id.vendor, id.product, id.version);
    LOGI("  name:     \"%s\"\n", name);
    LOGI("  location: \"%s\"\n"
         "  id:       \"%s\"\n", location, idstr);
    LOGI("  version:  %d.%d.%d\n",
        version >> 16, (version >> 8) & 0xff, version & 0xff);
#endif

    device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name, BUS_BLUETOOTH == id.bustype);
    if (device == NULL) {
        LOGE("out of memory");
        return -1;
    }

    device->fd = fd;
    mFDs[mFDCount].fd = fd;
    mFDs[mFDCount].events = POLLIN;
    mFDs[mFDCount].revents = 0;

    // Figure out the kinds of events the device reports.
    
    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
    memset(key_bitmask, 0, sizeof(key_bitmask));

    LOGV("Getting keys...");
    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
        //LOGI("MAP\n");
        //for (int i = 0; i < sizeof(key_bitmask); i++) {
        //    LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
        //}

        // See if this is a keyboard.  Ignore everything in the button range except for
        // gamepads which are also considered keyboards.
        if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
                || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
                        sizeof_bit_array(BTN_DIGI))
                || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
                        sizeof_bit_array(KEY_MAX + 1))) {
            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;

            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
            if (device->keyBitmask != NULL) {
                memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
            } else {
                delete device;
                LOGE("out of memory allocating key bitmask");
                return -1;
            }
        }
    }
    
    // See if this is a trackball (or mouse).
    if (test_bit(BTN_MOUSE, key_bitmask)) {
        uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
        memset(rel_bitmask, 0, sizeof(rel_bitmask));
        LOGV("Getting relative controllers...");
        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
                if (test_bit(BTN_LEFT, key_bitmask) && test_bit(BTN_RIGHT, key_bitmask))
                    device->classes |= INPUT_DEVICE_CLASS_MOUSE;
                else
                    device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
            }
        }
    }

    // See if this is a touch pad.
    uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
    memset(abs_bitmask, 0, sizeof(abs_bitmask));
    LOGV("Getting absolute controllers...");
    if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
        // Is this a new modern multi-touch driver?
        if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
                && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;

        // Is this an old style single-touch driver?
        } else if (test_bit(BTN_TOUCH, key_bitmask)
                && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
        }
    }

#ifdef EV_SW
    // figure out the switches this device reports
    uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
    memset(sw_bitmask, 0, sizeof(sw_bitmask));
    bool hasSwitches = false;
    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
        for (int i=0; i<EV_SW; i++) {
            //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
            if (test_bit(i, sw_bitmask)) {
                hasSwitches = true;
                if (mSwitches[i] == 0) {
                    mSwitches[i] = device->id;
                }
            }
        }
    }
    if (hasSwitches) {
        device->classes |= INPUT_DEVICE_CLASS_SWITCH;
    }
#endif

    if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
        char tmpfn[sizeof(name)];
        char keylayoutFilename[300];

        // a more descriptive name
        device->name = name;

        // replace all the spaces with underscores
        strcpy(tmpfn, name);
        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
            *p = '_';

        // find the .kl file we need for this device
        const char* root = getenv("ANDROID_ROOT");
        snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                 "%s/usr/keylayout/%s.kl", root, tmpfn);
        bool defaultKeymap = false;
        if (access(keylayoutFilename, R_OK)) {
            snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                     "%s/usr/keylayout/%s", root, "qwerty.kl");
            defaultKeymap = true;
        }
        status_t status = device->layoutMap->load(keylayoutFilename);
        if (status) {
            LOGE("Error %d loading key layout.", status);
        }

        // tell the world about the devname (the descriptive name)
        if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
            // the built-in keyboard has a well-known device ID of 0,
            // this device better not go away.
            mHaveFirstKeyboard = true;
            mFirstKeyboardId = device->id;
            property_set("hw.keyboards.0.devname", name);
        } else {
            // ensure mFirstKeyboardId is set to -something-.
            if (mFirstKeyboardId == 0) {
                mFirstKeyboardId = device->id;
            }
        }
        char propName[100];
        sprintf(propName, "hw.keyboards.%u.devname", device->id);
        property_set(propName, name);

        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
        if (hasKeycodeLocked(device, AKEYCODE_Q)) {
            device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
        }
        
        // See if this device has a DPAD.
        if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
            device->classes |= INPUT_DEVICE_CLASS_DPAD;
        }
        
        // See if this device has a gamepad.
        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
            if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
                device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
                break;
            }
        }

        LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
                device->id, name, propName, keylayoutFilename);
    }

    // If the device isn't recognized as something we handle, don't monitor it.
    if (device->classes == 0) {
        LOGV("Dropping device %s %p, id = %d\n", deviceName, device, devid);
        close(fd);
        delete device;
        return -1;
    }

    LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
         deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
         
    LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
         deviceName, device, mFDCount, devid, device->classes);

    mDevicesById[devid].device = device;
    device->next = mOpeningDevices;
    mOpeningDevices = device;
    mDevices[mFDCount] = device;

    mFDCount++;
    return 0;
}
Example #13
0
    I_NOSTATE(EVIOCGRAB, success),

    /* evdev */
    I_SIMPLE_STRUCT_IN(EVIOCGVERSION, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGID, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGREP, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGKEYCODE, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGKEYCODE_V2, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGEFFECTS, 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGABS(0), "EVIOCGABS", ABS_MAX, ioctl_insertion_parent_stateless),
    /* we define these with len==32, but they apply to any len */
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGBIT(0, 32), "EVIOCGBIT", EV_MAX, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGNAME(32), "EVIOCGNAME", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGPHYS(32), "EVIOCGPHYS", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGUNIQ(32), "EVIOCGUNIQ", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGPROP(32), "EVIOCGPROP", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGKEY(32), "EVIOCGKEY", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGLED(32), "EVIOCGLED", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGSND(32), "EVIOCGSND", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGSW(32), "EVIOCGSW", 0, ioctl_insertion_parent_stateless),

    /* this was introduced not too long ago */
#ifdef EVIOCGMTSLOTS
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGMTSLOTS(32), "EVIOCGMTSLOTS", 0, ioctl_insertion_parent_stateless),
#endif

    /* terminator */
    {0, 0, 0, "", NULL, NULL, NULL, NULL, NULL}
};
Example #14
0
static Bool
EvdevKbdInit (void)
{
    int         i;
    int         fd;
    int         n = 0;
    char        name[100];

    if (!EvdevInputType)
        EvdevInputType = KdAllocInputType ();

    for (i = 0; i < NUM_DEFAULT_EVDEV; i++)
    {
        fd = open (kdefaultEvdev1[i], 2);
        if (fd >= 0)
        {
            ioctl(fd, EVIOCGRAB, 1);

            ioctl(fd, EVIOCGNAME(sizeof(name)), name);
            ErrorF("Name is %s\n", name);
            ioctl(fd, EVIOCGPHYS(sizeof(name)), name);
            ErrorF("Phys Loc is %s\n", name);
            ioctl(fd, EVIOCGUNIQ(sizeof(name)), name);
            ErrorF("Unique is %s\n", name);

        }

        if (fd >= 0)
        {
            unsigned long   ev[NBITS(EV_MAX)];
            Kevdev          *ke;

            if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0)
            {
                perror ("EVIOCGBIT 0");
                close (fd);
                continue;
            }
            ke = xalloc (sizeof (Kevdev));
            if (!ke)
            {
                close (fd);
                continue;
            }
            memset (ke, '\0', sizeof (Kevdev));
            if (ISBITSET (ev, EV_KEY))
            {
                if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)),
                           ke->keybits) < 0)
                {
                    perror ("EVIOCGBIT EV_KEY");
                    xfree (ke);
                    close (fd);
                    continue;
                }
            }
            if (ISBITSET (ev, EV_REL))
            {
                if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)),
                           ke->relbits) < 0)
                {
                    perror ("EVIOCGBIT EV_REL");
                    xfree (ke);
                    close (fd);
                    continue;
                }
                for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--)
                    if (ISBITSET(ke->relbits, ke->max_rel))
                        break;
            }
            if (ISBITSET (ev, EV_ABS))
            {
                int i;

                if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)),
                           ke->absbits) < 0)
                {
                    perror ("EVIOCGBIT EV_ABS");
                    xfree (ke);
                    close (fd);
                    continue;
                }
                for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--)
                    if (ISBITSET(ke->absbits, ke->max_abs))
                        break;
                for (i = 0; i <= ke->max_abs; i++)
                {
                    if (ISBITSET (ke->absbits, i))
                        if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0)
                        {
                            perror ("EVIOCGABS");
                            break;
                        }
                    ke->prevabs[i] = ABS_UNSET;
                }
                if (i <= ke->max_abs)
                {
                    xfree (ke);
                    close (fd);
                    continue;
                }
            }
            if (KdRegisterFd (EvdevInputType, fd, EvdevRead1, NULL))
                n++;
        }
    }
    return TRUE;
}
Example #15
0
static int
evdev_read_ioctl(struct tcb *const tcp, const unsigned int code,
		 const kernel_ulong_t arg)
{
	/* fixed-number fixed-length commands */
	switch (code) {
		case EVIOCGVERSION:
			tprints(", ");
			printnum_int(tcp, arg, "%#x");
			return 1;
		case EVIOCGEFFECTS:
			tprints(", ");
			printnum_int(tcp, arg, "%u");
			return 1;
		case EVIOCGID:
			return getid_ioctl(tcp, arg);
# ifdef EVIOCGREP
		case EVIOCGREP:
			return repeat_ioctl(tcp, arg);
# endif
		case EVIOCGKEYCODE:
			return keycode_ioctl(tcp, arg);
# ifdef EVIOCGKEYCODE_V2
		case EVIOCGKEYCODE_V2:
			return keycode_V2_ioctl(tcp, arg);
# endif
	}

	/* fixed-number variable-length commands */
	switch (_IOC_NR(code)) {
# ifdef EVIOCGMTSLOTS
		case _IOC_NR(EVIOCGMTSLOTS(0)):
			return mtslots_ioctl(tcp, code, arg);
# endif
		case _IOC_NR(EVIOCGNAME(0)):
		case _IOC_NR(EVIOCGPHYS(0)):
		case _IOC_NR(EVIOCGUNIQ(0)):
			tprints(", ");
			if (syserror(tcp))
				printaddr(arg);
			else
				printstrn(tcp, arg, tcp->u_rval);
			return 1;
# ifdef EVIOCGPROP
		case _IOC_NR(EVIOCGPROP(0)):
			return decode_bitset(tcp, arg, evdev_prop,
					     INPUT_PROP_MAX, "PROP_???");
# endif
		case _IOC_NR(EVIOCGSND(0)):
			return decode_bitset(tcp, arg, evdev_snd,
					     SND_MAX, "SND_???");
# ifdef EVIOCGSW
		case _IOC_NR(EVIOCGSW(0)):
			return decode_bitset(tcp, arg, evdev_switch,
					     SW_MAX, "SW_???");
# endif
		case _IOC_NR(EVIOCGKEY(0)):
			return decode_bitset(tcp, arg, evdev_keycode,
					     KEY_MAX, "KEY_???");
		case _IOC_NR(EVIOCGLED(0)):
			return decode_bitset(tcp, arg, evdev_leds,
					     LED_MAX, "LED_???");
	}

	/* multi-number fixed-length commands */
	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
		return abs_ioctl(tcp, arg);

	/* multi-number variable-length commands */
	if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
		return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);

	return 0;
}
status_t EvdevDeviceNode::queryProperties() {
    char buffer[80];

    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGNAME(sizeof(buffer) - 1), buffer)) < 1) {
        ALOGV("could not get device name for %s.", mPath.c_str());
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        mName = buffer;
    }

    int driverVersion;
    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGVERSION, &driverVersion))) {
        ALOGE("could not get driver version for %s. err=%d", mPath.c_str(), errno);
        return -errno;
    }

    struct input_id inputId;
    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGID, &inputId))) {
        ALOGE("could not get device input id for %s. err=%d", mPath.c_str(), errno);
        return -errno;
    }
    mBusType = inputId.bustype;
    mVendorId = inputId.vendor;
    mProductId = inputId.product;
    mVersion = inputId.version;

    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPHYS(sizeof(buffer) - 1), buffer)) < 1) {
        ALOGV("could not get location for %s.", mPath.c_str());
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        mLocation = buffer;
    }

    if (TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGUNIQ(sizeof(buffer) - 1), buffer)) < 1) {
        ALOGV("could not get unique id for %s.", mPath.c_str());
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        mUniqueId = buffer;
    }

    ALOGV("add device %s", mPath.c_str());
    ALOGV("  bus:        %04x\n"
          "  vendor:     %04x\n"
          "  product:    %04x\n"
          "  version:    %04x\n",
        mBusType, mVendorId, mProductId, mVersion);
    ALOGV("  name:       \"%s\"\n"
          "  location:   \"%s\"\n"
          "  unique_id:  \"%s\"\n"
          "  descriptor: (TODO)\n"
          "  driver:     v%d.%d.%d",
        mName.c_str(), mLocation.c_str(), mUniqueId.c_str(),
        driverVersion >> 16, (driverVersion >> 8) & 0xff, (driverVersion >> 16) & 0xff);

    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_KEY, sizeof(mKeyBitmask)), mKeyBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_ABS, sizeof(mAbsBitmask)), mAbsBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_REL, sizeof(mRelBitmask)), mRelBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_SW,  sizeof(mSwBitmask)),  mSwBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_LED, sizeof(mLedBitmask)), mLedBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGBIT(EV_FF,  sizeof(mFfBitmask)),  mFfBitmask));
    TEMP_FAILURE_RETRY(ioctl(mFd, EVIOCGPROP(sizeof(mPropBitmask)), mPropBitmask));

    queryAxisInfo();

    return OK;
}
Example #17
0
static unsigned char send_device_info(IEContext* ctx, unsigned int reply_id)
{
    dterm_mark_t msg;
    dterm_t dt;
    int len = 0;
    char name[256];
    char topology[256];
    char uniq_id[256];

    struct input_id id;

    // Get device id.
    if (ioctl(ctx->mDescriptor, EVIOCGID, &id) < 0)
    {
        return IEDRV_RES_IO_ERROR;
    }

    if ((len = ioctl(ctx->mDescriptor, EVIOCGNAME(sizeof(name) - 1), name)) < 0) {
        return IEDRV_RES_IO_ERROR;
    }
    name[len] = 0;

    if ((len = ioctl(ctx->mDescriptor, EVIOCGPHYS(sizeof(topology) - 1), topology)) < 0) {
        return IEDRV_RES_IO_ERROR;
    }
    topology[len] = 0;

    if ((len = ioctl(ctx->mDescriptor, EVIOCGUNIQ(sizeof(uniq_id) - 1), uniq_id)) < 0)
        uniq_id[0] = 0;

    uniq_id[len] = 0;

    dterm_init(&dt);

    dterm_tuple_begin(&dt, &msg); {
        dterm_mark_t prop;

        dterm_atom(&dt, ie_device_info);
        dterm_port(&dt, ctx->mDport);
        dterm_int(&dt, reply_id);


        //
        // Setup { id, Bustype, Vendor, Product, Version, Name}
        //
        dterm_tuple_begin(&dt, &prop); {
            dterm_atom(&dt, ie_drv_dev_id);
            dterm_string(&dt, uniq_id, strlen(uniq_id));
            dterm_string(&dt, name, strlen(name));
            dterm_atom(&dt, *bus_atoms[id.bustype]);
            dterm_int(&dt, id.vendor);
            dterm_int(&dt, id.product);
            dterm_int(&dt, id.version);
            dterm_string(&dt, topology, strlen(topology));

            //
            // Setup [{ capability, [ { Cap, [X] }, { Cap, [Y] }, ...}, ...]
            //
            add_cap(&dt,  ctx->mDescriptor);
            dterm_tuple_end(&dt, &prop);
        }
    }
    dterm_tuple_end(&dt, &msg);
    driver_output_term(ctx->mPort, dterm_data(&dt), dterm_used_size(&dt));
    dterm_finish(&dt);


    return IEDRV_RES_OK;
}
Example #18
0
static int open_device(const char *device, int print_flags)
{
    int version;
    int fd;
    int clkid = CLOCK_MONOTONIC;
    struct pollfd *new_ufds;
    char **new_device_names;
    char name[80];
    char location[80];
    char idstr[80];
    struct input_id id;

    fd = open(device, O_RDONLY | O_CLOEXEC);
    if(fd < 0) {
        if(print_flags & PRINT_DEVICE_ERRORS)
            fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
        return -1;
    }
    
    if(ioctl(fd, EVIOCGVERSION, &version)) {
        if(print_flags & PRINT_DEVICE_ERRORS)
            fprintf(stderr, "could not get driver version for %s, %s\n", device, strerror(errno));
        return -1;
    }
    if(ioctl(fd, EVIOCGID, &id)) {
        if(print_flags & PRINT_DEVICE_ERRORS)
            fprintf(stderr, "could not get driver id for %s, %s\n", device, strerror(errno));
        return -1;
    }
    name[sizeof(name) - 1] = '\0';
    location[sizeof(location) - 1] = '\0';
    idstr[sizeof(idstr) - 1] = '\0';
    if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
        //fprintf(stderr, "could not get device name for %s, %s\n", device, strerror(errno));
        name[0] = '\0';
    }
    if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
        //fprintf(stderr, "could not get location for %s, %s\n", device, strerror(errno));
        location[0] = '\0';
    }
    if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
        //fprintf(stderr, "could not get idstring for %s, %s\n", device, strerror(errno));
        idstr[0] = '\0';
    }

    if (ioctl(fd, EVIOCSCLOCKID, &clkid) != 0) {
        fprintf(stderr, "Can't enable monotonic clock reporting: %s\n", strerror(errno));
        // a non-fatal error
    }

    new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
    if(new_ufds == NULL) {
        fprintf(stderr, "out of memory\n");
        return -1;
    }
    ufds = new_ufds;
    new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
    if(new_device_names == NULL) {
        fprintf(stderr, "out of memory\n");
        return -1;
    }
    device_names = new_device_names;

    if(print_flags & PRINT_DEVICE)
        printf("add device %d: %s\n", nfds, device);
    if(print_flags & PRINT_DEVICE_INFO)
        printf("  bus:      %04x\n"
               "  vendor    %04x\n"
               "  product   %04x\n"
               "  version   %04x\n",
               id.bustype, id.vendor, id.product, id.version);
    if(print_flags & PRINT_DEVICE_NAME)
        printf("  name:     \"%s\"\n", name);
    if(print_flags & PRINT_DEVICE_INFO)
        printf("  location: \"%s\"\n"
               "  id:       \"%s\"\n", location, idstr);
    if(print_flags & PRINT_VERSION)
        printf("  version:  %d.%d.%d\n",
               version >> 16, (version >> 8) & 0xff, version & 0xff);

    if(print_flags & PRINT_POSSIBLE_EVENTS) {
        print_possible_events(fd, print_flags);
    }

    if(print_flags & PRINT_INPUT_PROPS) {
        print_input_props(fd);
    }
    if(print_flags & PRINT_HID_DESCRIPTOR) {
        print_hid_descriptor(id.bustype, id.vendor, id.product);
    }

    ufds[nfds].fd = fd;
    ufds[nfds].events = POLLIN;
    device_names[nfds] = strdup(device);
    nfds++;

    return 0;
}
Example #19
0
/* another option to this mess (as the hashing thing doesn't seem to work out
 * is to move identification/etc. to another level and just let whatever device
 * node generator is active populate with coherent names. and use a hash of that
 * name as the ID */
static bool identify(int fd, const char* path,
	char* label, size_t label_sz, unsigned short* dnum)
{
	if (-1 == ioctl(fd, EVIOCGNAME(label_sz), label)){
		debug_print("input/identify: bad EVIOCGNAME, setting unknown\n");
		snprintf(label, label_sz, "unknown");
	}
	else
		verbose_print(
			"input/identify(%d): %s name resolved to %s", fd, path, label);

	struct input_id nodeid;
	if (-1 == ioctl(fd, EVIOCGID, &nodeid)){
		debug_print(
			"input/identify(%d): no EVIOCGID, reason:%s", fd, strerror(errno));
		return false;
	}

/*
 * first, check if any other subsystem knows about this one and ignore if so
 */
	if (arcan_led_known(nodeid.vendor, nodeid.product)){
		debug_print(
			"led subsys know %d, %d\n", (int)nodeid.vendor, (int)nodeid.product);
		arcan_led_init();
		return false;
	}

/* didn't find much on how unique eviocguniq actually was, nor common lengths
 * or what not so just mix them in a buffer, hash and let unsigned overflow
 * modulo take us down to 16bit */
	size_t bpl = sizeof(long) * 8;
	size_t nbits = ((EV_MAX)-1) / bpl + 1;

	char buf[12 + nbits * sizeof(long)];
	char bbuf[sizeof(buf)];
	memset(buf, '\0', sizeof(buf));
	memset(bbuf, '\0', sizeof(bbuf));

/* some test devices here answered to the ioctl and returned full empty UNIQs,
 * do something to lower the likelihood of collisions */
	unsigned long hash = 5381;

	if (-1 == ioctl(fd, EVIOCGUNIQ(sizeof(buf)), buf) ||
		memcmp(buf, bbuf, sizeof(buf)) == 0){

		size_t llen = strlen(label);
		for (size_t i = 0; i < llen; i++)
			hash = ((hash << 5) + hash) + label[i];

		llen = strlen(path);
		for (size_t i = 0; i < llen; i++)
			hash  = ((hash << 5) + hash) + path[i];

		buf[11] ^= nodeid.vendor >> 8;
		buf[10] ^= nodeid.vendor;
		buf[9] ^= nodeid.product >> 8;
		buf[8] ^= nodeid.product;
		buf[7] ^= nodeid.version >> 8;
		buf[6] ^= nodeid.version;

/* even this point has a few collisions, particularly some keyboards and mice
 * that don't respond to CGUNIQ and expose multiple- subdevices but with
 * different button/axis count */
		ioctl(fd, EVIOCGBIT(0, EV_MAX), &buf);
	}
Example #20
0
static int open_device(const char *device)
{
    int version;
    int fd;
    struct pollfd *new_ufds;
    char **new_device_names;
    char name[80];
    char location[80];
    char idstr[80];
    struct input_id id;

    fd = open(device, O_RDWR);
    if(fd < 0) {
        fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
        return -1;
    }
    
    if(ioctl(fd, EVIOCGVERSION, &version)) {
        fprintf(stderr, "could not get driver version for %s, %s\n", device, strerror(errno));
        return -1;
    }
    if(ioctl(fd, EVIOCGID, &id)) {
        fprintf(stderr, "could not get driver id for %s, %s\n", device, strerror(errno));
        return -1;
    }
    name[sizeof(name) - 1] = '\0';
    location[sizeof(location) - 1] = '\0';
    idstr[sizeof(idstr) - 1] = '\0';
    if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
        //fprintf(stderr, "could not get device name for %s, %s\n", device, strerror(errno));
        name[0] = '\0';
    }
    if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
        //fprintf(stderr, "could not get location for %s, %s\n", device, strerror(errno));
        location[0] = '\0';
    }
    if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
        //fprintf(stderr, "could not get idstring for %s, %s\n", device, strerror(errno));
        idstr[0] = '\0';
    }

    new_ufds = (pollfd*)realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
    if(new_ufds == NULL) {
        fprintf(stderr, "out of memory\n");
        return -1;
    }
    ufds = new_ufds;
    new_device_names = (char**)realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
    if(new_device_names == NULL) {
        fprintf(stderr, "out of memory\n");
        return -1;
    }
    device_names = new_device_names;

    printf("add device %d: %s \"%s\"\n", nfds, device, name);

    ufds[nfds].fd = fd;
    ufds[nfds].events = POLLIN;
    device_names[nfds] = strdup(device);
    nfds++;

    return 0;
}