-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Wed, 6 Nov 2002 17:51, Pete Zaitcev wrote:
> > From: Brad Hards <[EMAIL PROTECTED]>
> > Date: Wed, 6 Nov 2002 16:48:08 +1100
> >
> > > 2. Ask logitech - I have a contact that might work.
> >
> > Logitech says:
> > <quote>
> > Yes, the battery status information comes from a vendor command.
> >[...]
>
> This is wonderful, however I am concerned that hiddev cannot be
> used while input is using hid. This seems a little too limiting.
> How am I supposed to implement the applet to indicate the battery
> charge, for example? Adding Logitech-specific control messages
> to mousedev does not look appealing.
OK, putz off my previous ideas.

I've looked over the documentation, and its mainly vendor commands. I've 
implemented a command-line test harness for the resolution swapping (a few 
devices have switchable 400cpi/800cpi sensors) - see attached example, which 
requires libusb (http://libusb.sf.net)

The complex part for the battery info (which was the original problem), and a 
lot of the other status reporting for cordless devices, is that the device 
(ab)uses the HID reports to signal that some of the status information has 
changed. 

AFAICT, the whole thing can be done from userspace using the usbfs (or libusb, 
over the top of usbfs), except for that status change notification. Maybe we 
just have to use polling :(

Brad
- -- 
http://linux.conf.au. 22-25Jan2003. Perth, Aust. I'm registered. Are you?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE9z4zuW6pHgIdAuOMRAjQKAJ94bhqNoPlf0W3wx6FOuUA0RiasHQCgwzLh
5kV3zZ1Do5LWccMjnbhfBp0=
=fYGj
-----END PGP SIGNATURE-----
/*
 * Get / set resolution on logitech dual optical mice.
 * Requires libusb.
 */

#include <stdio.h>
#include <getopt.h>
#include <usb.h>

#define VERSION "0.0"

#define VENDOR_LOGITECH 0x046D

int get_resolution(struct usb_device *dev)
{
    char resolution;
    int result;
    usb_dev_handle *usb_h;

    usb_h = usb_open(dev);
    if (0 > usb_h) {
	printf("Error opening usbfs file: %s", usb_strerror());
	return -1;
    }

    result =  usb_control_msg(usb_h,
			      USB_TYPE_VENDOR | USB_ENDPOINT_IN,
			      0x01,
			      0x000E,
			      0x0000,
			      &resolution,
			      0x0001,
			      100);

    if (0 > result) {
	printf("Error getting resolution from device : %s", usb_strerror());
    }

    usb_close(usb_h);

    return resolution;
}

/* resolution should be 0x03 for 400cpi, 0x04 for 800cpi */
int set_resolution(struct usb_device *dev, int resolution)
{
    usb_dev_handle *usb_h;

    usb_h = usb_open(dev);
    usb_control_msg(usb_h, USB_TYPE_VENDOR, 0x02, 0x000E, resolution,
		    NULL,  0x0000, 100);
    usb_close(usb_h);

    return 0;
}

void usage(void)
{
    printf("Logitech Mouse Applet, Version %s\n", VERSION);
    printf(" --set-res X   set the sensor resolution to X, where X is 400 or 800\n");
    printf(" --get-res     read the current sensor resolution\n");
    printf(" --version     display the program version\n");
    printf(" --help        print this usage information\n");
    printf(" -s X          same as --set-res X\n");
    printf(" -g            same as --get-res\n");
    printf(" -v            same as --version\n");
    printf(" -h            same as --help\n");
    printf("Copyright (C) 2002 Brad Hards <[EMAIL PROTECTED]>\n");
}

void version(void)
{
    printf("Logitech Mouse Applet, Version %s\n", VERSION);
}

struct device_table {
    int idVendor;
    int idProduct;
    char* Model;
    char* Name;
} device_table[] = {
    { VENDOR_LOGITECH, 0xC00E, "M-BJ58", "Wheel Mouse Optical" },
    { VENDOR_LOGITECH, 0xC00F, "M-BJ79", "MouseMan Traveler" },
    { VENDOR_LOGITECH, 0xC012, "M-BL63B", "MouseMan Dual Optical" },
    { VENDOR_LOGITECH, 0xC024, "M-BP82", "MX300 Optical Mouse" },
    { VENDOR_LOGITECH, 0xC025, "M-BP81A", "MX500 Optical Mouse" },
    { VENDOR_LOGITECH, 0xC031, "M-UT58A", "iFeel Mouse (silver)" },
    { 0, 0, 0, 0 }
};

int main(int argc, char **argv)
{
    struct usb_bus *bus;
    struct usb_device *dev;
    int c;
    int resolution = 0;
    int n;

    while (1) {
        int option_index = 0;
        static struct option long_options[] = {
            {"get-res", 0, 0, 'g'},
            {"help", 0, 0, 'h'},
            {"set-res", 1, 0, 's'},
            {"version", 0, 0, 'v'},
            {0, 0, 0, 0}
        };

        c = getopt_long  (argc, argv, "ghs:v",
                 long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'g':
	    resolution = 0;
            break;
        case 'h':
	    usage();
	    return 0;
            break;
        case 's':
	    if (!strcmp("400", optarg))
		resolution = 400;
	    else if (!strcmp("800", optarg))
		resolution = 800;
	    else
		printf("Bad argument (should be 400 or 800)\n");
            break;
        case 'v':
	    version();
	    return 0;
            break;

        default:
	    usage();
	    break;
        }
    }

    usb_init();

    usb_find_busses();
    usb_find_devices();

    for (bus = usb_busses; bus; bus = bus->next) {
	for (dev = bus->devices; dev; dev = dev->next) {

	    for (n = 0; device_table[n].idVendor; n++)
		if ( (device_table[n].idVendor == dev->descriptor.idVendor) &&
		     (device_table[n].idProduct == dev->descriptor.idProduct) ) {
		    printf("%s/%s     %04X/%04X  \t%s \t%s\n",
			   bus->dirname,
			   dev->filename,
			   dev->descriptor.idVendor,
			   dev->descriptor.idProduct,
			   device_table[n].Model,
			   device_table[n].Name);
		    
		    if (0 == resolution) {
			resolution = get_resolution(dev);
			printf("   Resolution: %x ", resolution);
			switch (resolution)
			    {
			    case 0: printf("(You probably aren't root)\n");
				break;
			    case 3: printf("(400cpi)\n");
				break;
			    case 4: printf("(800cpi)\n");
				break;
			    default: printf("(Unexpected result:%i)\n", resolution);
				break;
			    }
		    } else {
			if (400 == resolution)
			    set_resolution(dev, 0x03);
			else 
			    set_resolution(dev, 0x04);
		    }
		}
	}
    }
    return 0;

}

Reply via email to