mx900 driver for linux

un paio di settimane fa ho comprato un mouse bluetooth della logitech (mx900)

il mouse in se per se va pero’ ci sono tanti bottoni che non vengono gestiti correttamente

dopo 5 giorni spesi nel cercare di capire come patchare hid del kernel per gestire tali bottoni in una maniera semiseria ho gettato la spugna e scritto questo driver

il risultato e’ ottimo pero’ il modo utilizzato per raggiungerlo abbastanza patetico.

il risultato e’ stato 200 righe di codice con i bottoni hardcoded.

qui il codice


#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#define GETBIT(v,n) ((v>>(n))&0x01)
#define SETBIT(v,n) (v |= (0x01<<(n)))
/* Globals */
static int uinp_fd = -1;
struct uinput_user_dev uinp; // uInput device structure
struct input_event event; // Input event structure
/* Setup the uinput device */
int setup_uinput_device () {
// Temporary variable
int i = 0;
// Open the input device
uinp_fd = open ("/dev/input/uinput", O_WRONLY | O_NDELAY);
if (uinp_fd <= 0)
{
printf ("Unable to open uinput device. Are you root? \n");
return -1;
}
memset (&uinp, 0, sizeof (uinp)); // Intialize the uInput device to NULL
strncpy (uinp.name, "Logitech Mx 900", UINPUT_MAX_NAME_SIZE);
uinp.id.version = 4;
uinp.id.bustype = BUS_USB;
// Setup the uinput device
ioctl (uinp_fd, UI_SET_EVBIT, EV_KEY);
ioctl (uinp_fd, UI_SET_EVBIT, EV_REL);
ioctl (uinp_fd, UI_SET_RELBIT, REL_X);
ioctl (uinp_fd, UI_SET_RELBIT, REL_Y);
ioctl (uinp_fd, UI_SET_RELBIT, REL_WHEEL);
for (i = 0; i < 256; i++)
ioctl (uinp_fd, UI_SET_KEYBIT, i);
ioctl (uinp_fd, UI_SET_KEYBIT, BTN_MOUSE);
ioctl (uinp_fd, UI_SET_KEYBIT, BTN_LEFT);
ioctl (uinp_fd, UI_SET_KEYBIT, BTN_MIDDLE);
ioctl (uinp_fd, UI_SET_KEYBIT, BTN_RIGHT);
/* Create input device into input sub-system */
write (uinp_fd, &uinp, sizeof (uinp));
if (ioctl (uinp_fd, UI_DEV_CREATE))
{
printf ("Unable to create UINPUT device.");
return -1;
}
return 1;
}
void move_mouse (int x, int y) {
memset (&event, 0, sizeof (event));
gettimeofday (&event.time, NULL);
event.type = EV_REL;
event.code = REL_X;
event.value = x;
write (uinp_fd, &event, sizeof (event));
event.type = EV_REL;
event.code = REL_Y;
event.value = y;
write (uinp_fd, &event, sizeof (event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write (uinp_fd, &event, sizeof (event));
}
void report_button_and_wheel (char button_byte, char wheel) {
memset (&event, 0, sizeof (event));
gettimeofday (&event.time, NULL);
event.type = EV_KEY;
event.code = BTN_LEFT;
event.value = GETBIT(button_byte,0);
write(uinp_fd, &event, sizeof (event));
event.type = EV_KEY;
event.code = BTN_RIGHT;
event.value = GETBIT(button_byte,1);
write(uinp_fd, &event, sizeof (event));
event.type = EV_KEY;
event.code = BTN_MIDDLE;
event.value = GETBIT(button_byte,2);
write(uinp_fd, &event, sizeof (event));
event.type = EV_KEY;
event.code = KEY_ESC;
event.value = GETBIT(button_byte,3);
write(uinp_fd, &event, sizeof (event));
event.type = EV_KEY;
event.code = KEY_LEFTALT;
event.value = GETBIT(button_byte,4);
write(uinp_fd, &event, sizeof (event));
event.type = EV_KEY;
event.code = KEY_F12;
event.value = GETBIT(button_byte,5);
write(uinp_fd, &event, sizeof (event));
event.type = EV_KEY;
event.code = KEY_K;
event.value = GETBIT(button_byte,6);
write(uinp_fd, &event, sizeof (event));
event.type = EV_KEY;
event.code = KEY_J;
event.value = GETBIT(button_byte,7);
write(uinp_fd, &event, sizeof (event));
if (GETBIT(button_byte,6)==0 && GETBIT(button_byte,7)==0){
event.type = EV_REL;
event.code = REL_WHEEL;
event.value = wheel;
write(uinp_fd, &event, sizeof (event));
}
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write (uinp_fd, &event, sizeof (event));
}
int main () {
struct sockaddr_l2 s_addr = { 0 };
struct sockaddr_l2 t_addr = { 0 };
int s, t, s_status, t_status, bytes_read;
char dest[18] = "00:07:61:09:59:46";
start:
s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
t = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
s_addr.l2_family = AF_BLUETOOTH;
s_addr.l2_psm = htobs(0x0013);
str2ba( dest, &s_addr.l2_bdaddr );
t_addr.l2_family = AF_BLUETOOTH;
t_addr.l2_psm = htobs(0x0011);
str2ba( dest, &t_addr.l2_bdaddr );
s_status = connect(s, (struct sockaddr *)&s_addr, sizeof(s_addr));
if ( s_status != 0){
fprintf(stderr,"unable to find the bluetooth device, retring ...\n");
goto start;
}
t_status = connect(t, (struct sockaddr *)&t_addr, sizeof(t_addr));
fprintf(stderr,"Connected, start reading...\n");
if (setup_uinput_device () = 0){
short int rel_x, rel_y, temp_x, temp_y;
temp_x = buf[4];
temp_x = temp_x <>4;
temp_y = temp_y&0x000f;
rel_y = buf[5];
rel_y = rel_y << 4;
rel_y = rel_y & 0x0ff0;
rel_y = rel_y + temp_y;
if (GETBIT(rel_x,11)==1)
rel_x = rel_x | 0xf000;
if (GETBIT(rel_y,11)==1)
rel_y = rel_y | 0xf000;
move_mouse (rel_x,rel_y);
report_button_and_wheel(buf[2],buf[6]);
}
else {
printf("somethings wrong, or everything is ok\n");
goto start;
}
}
close(s);
close(t);
return 0;
}

modificare il mac address del mouse

compilare con

gcc -Wall -o mx900driver mx900driver.c -lbluetooth

sudo mx900driver

freccia laterale avanti = Alt

freccia laterale indietro = Esc

Tasto centrale con 2 quadrati disegnati dentro = F12

Freccia su (sopra alla rotella) = k

Freccia giu (sotto alla rotella) = j

gli ultimi 2 servono per scorrere gli item su google reader (o su altri siti se usate jackassify)

il resto dei tasti hanno una funzione normale

per modificare il comportamento modificate la funzione report_button_and_wheel cambiano l’event.code

il tutto e’ molto grezzo , se a qualcuno interessa miglioro le cose e faccio qualcosa di un po’ + usabile

p.s. per ora non ho idea se questa roba funzioni su installazioni a 64bit

2 Risposte

  1. non raggiungerò mai le tue programming skillz, visicappasette.

  2. U A O !!!
    Io ho un millantesimo delle tue conoscenze, però mi piaceva fare in modo che il mio touchpad del portatile Acer Aspire 5920 riuscisse a far “scrollare” su e giù e a destra e sinistra le pagine grazie ad un quadratino che in Windows ha queste funzioni, e che Ubuntu 32 bit mi riconosce come tasto destro del mouse.

    Hai idea di cosa parlo?
    Fammi sapere a danielesil88@yahoo.it

Lascia un commento