Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhid/mouse/mousedev.c

    rf90c0d6 re60436b  
    3939#include <usb/classes/hid.h>
    4040#include <usb/classes/hidreq.h>
    41 #include <usb/classes/hidut.h>
    4241#include <errno.h>
    4342#include <str_error.h>
    4443#include <ipc/mouse.h>
    45 #include <io/console.h>
    46 
    47 #include <ipc/kbd.h>
    48 #include <io/keycode.h>
    4944
    5045#include "mousedev.h"
    5146#include "../usbhid.h"
    52 
    53 #define NAME "mouse"
    5447
    5548/*----------------------------------------------------------------------------*/
     
    6558
    6659const char *HID_MOUSE_FUN_NAME = "mouse";
    67 const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
    6860const char *HID_MOUSE_CLASS_NAME = "mouse";
    69 const char *HID_MOUSE_WHEEL_CLASS_NAME = "keyboard";
    7061
    7162/** Default idle rate for mouses. */
    7263static const uint8_t IDLE_RATE = 0;
    73 static const size_t USB_MOUSE_BUTTON_COUNT = 3;
    7464
    7565/*----------------------------------------------------------------------------*/
     
    125115       
    126116        if (hid_dev == NULL || hid_dev->data == NULL) {
    127                 usb_log_debug("default_connection_handler: Missing "
    128                     "parameters.\n");
    129117                async_answer_0(icallid, EINVAL);
    130118                return;
     
    135123        usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
    136124       
    137         int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0)
    138                      ? &mouse_dev->mouse_phone : &mouse_dev->wheel_phone;
    139        
    140125        if (method == IPC_M_CONNECT_TO_ME) {
    141126                int callback = IPC_GET_ARG5(*icall);
    142127
    143                 if (*phone != -1) {
    144                         usb_log_debug("default_connection_handler: Console "
    145                             "phone to mouse already set.\n");
     128                if (mouse_dev->console_phone != -1) {
    146129                        async_answer_0(icallid, ELIMIT);
    147                         //async_answer_0(icallid, EOK);
    148130                        return;
    149131                }
    150132
    151                 *phone = callback;
     133                mouse_dev->console_phone = callback;
    152134                usb_log_debug("Console phone to mouse set ok (%d).\n", callback);
    153135                async_answer_0(icallid, EOK);
     
    155137        }
    156138
    157         usb_log_debug("default_connection_handler: Invalid function.\n");
    158139        async_answer_0(icallid, EINVAL);
    159140}
     
    167148                return NULL;
    168149        }
    169         mouse->mouse_phone = -1;
    170         mouse->wheel_phone = -1;
     150        mouse->console_phone = -1;
    171151       
    172152        return mouse;
     
    180160       
    181161        // hangup phone to the console
    182         if ((*mouse_dev)->mouse_phone >= 0) {
    183                 async_hangup((*mouse_dev)->mouse_phone);
    184         }
    185        
    186         if ((*mouse_dev)->wheel_phone >= 0) {
    187                 async_hangup((*mouse_dev)->wheel_phone);
     162        if ((*mouse_dev)->console_phone >= 0) {
     163                async_hangup((*mouse_dev)->console_phone);
    188164        }
    189165       
     
    194170/*----------------------------------------------------------------------------*/
    195171
    196 static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
    197 {
    198         console_event_t ev;
    199        
    200         ev.type = KEY_PRESS;
    201         ev.key = (wheel > 0) ? KC_UP : (wheel < 0) ? KC_DOWN : 0;
    202         ev.mods = 0;
    203         ev.c = 0;
    204 
    205         if (mouse_dev->wheel_phone < 0) {
    206                 usb_log_warning(
    207                     "Connection to console not ready, key discarded.\n");
    208                 return;
    209         }
    210        
    211         int count = (wheel < 0) ? -wheel : wheel;
    212         int i;
    213        
    214         for (i = 0; i < count * 3; ++i) {
    215                 usb_log_debug2("Sending key %d to the console\n", ev.key);
    216                 async_msg_4(mouse_dev->wheel_phone, KBD_EVENT, ev.type,
    217                     ev.key, ev.mods, ev.c);
    218                 // send key release right away
    219                 async_msg_4(mouse_dev->wheel_phone, KBD_EVENT, KEY_RELEASE,
    220                     ev.key, ev.mods, ev.c);
    221         }
    222 }
    223 
    224 /*----------------------------------------------------------------------------*/
    225 
    226 static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev, uint8_t *buffer,
    227     size_t buffer_size)
    228 {
    229         usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
    230        
     172static bool usb_mouse_process_boot_report(usb_mouse_t *mouse_dev,
     173    uint8_t *buffer, size_t buffer_size)
     174{
    231175        usb_log_debug2("got buffer: %s.\n",
    232176            usb_debug_str_buffer(buffer, buffer_size, 0));
    233        
    234         if (mouse_dev->mouse_phone < 0) {
    235                 usb_log_error(NAME " No console phone.\n");
    236                 return false;   // ??
    237         }
    238 
    239         /*
    240          * parse the input report
    241          */
    242        
    243         usb_log_debug(NAME " Calling usb_hid_parse_report() with "
    244             "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
    245        
    246         uint8_t report_id;
    247        
    248         int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    249             &report_id);
    250        
    251         if (rc != EOK) {
    252                 usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n",
    253                     str_error(rc));
    254                 return true;
    255         }
    256        
    257         /*
    258          * X
    259          */
    260         int shift_x = 0;
    261        
    262         usb_hid_report_path_t *path = usb_hid_report_path();
    263         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
    264             USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    265 
    266         usb_hid_report_path_set_report_id(path, report_id);
    267 
    268         usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    269             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END,
    270             USB_HID_REPORT_TYPE_INPUT);
    271 
    272         if (field != NULL) {
    273                 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    274                     field->usage);
    275                 shift_x = field->value;
    276         }
    277 
    278         usb_hid_report_path_free(path);
    279        
    280         /*
    281          * Y
    282          */
    283         int shift_y = 0;
    284        
    285         path = usb_hid_report_path();
    286         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
    287             USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    288 
    289         usb_hid_report_path_set_report_id(path, report_id);
    290 
    291         field = usb_hid_report_get_sibling(
    292             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END,
    293             USB_HID_REPORT_TYPE_INPUT);
    294 
    295         if (field != NULL) {
    296                 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    297                     field->usage);
    298                 shift_y = field->value;
    299         }
    300 
    301         usb_hid_report_path_free(path);
    302        
    303         if ((shift_x != 0) || (shift_y != 0)) {
    304                 async_req_2_0(mouse_dev->mouse_phone,
    305                     MEVENT_MOVE, shift_x, shift_y);
    306         }
    307        
    308         /*
    309          * Wheel
    310          */
    311         int wheel = 0;
    312        
    313         path = usb_hid_report_path();
    314         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
    315             USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    316 
    317         usb_hid_report_path_set_report_id(path, report_id);
    318        
    319         field = usb_hid_report_get_sibling(
    320             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END,
    321             USB_HID_REPORT_TYPE_INPUT);
    322 
    323         if (field != NULL) {
    324                 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    325                     field->usage);
    326                 wheel = field->value;
    327         }
    328 
    329         usb_hid_report_path_free(path);
    330        
    331         // send arrow up for positive direction and arrow down for negative
    332         // direction; three arrows for difference of 1
    333         usb_mouse_send_wheel(mouse_dev, wheel);
    334        
    335        
    336         /*
    337          * Buttons
    338          */
    339         path = usb_hid_report_path();
    340         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
    341         usb_hid_report_path_set_report_id(path, report_id);
    342        
    343         field = usb_hid_report_get_sibling(
    344             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    345             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    346             USB_HID_REPORT_TYPE_INPUT);
    347 
    348         while (field != NULL) {
    349                 usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value,
    350                     field->usage);
    351                
    352                 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
    353                     && field->value != 0) {
    354                         async_req_2_0(mouse_dev->mouse_phone,
    355                             MEVENT_BUTTON, field->usage, 1);
    356                         mouse_dev->buttons[field->usage - field->usage_minimum]
    357                             = field->value;
    358                 } else if (
    359                     mouse_dev->buttons[field->usage - field->usage_minimum] != 0
    360                     && field->value == 0) {
    361                        async_req_2_0(mouse_dev->mouse_phone,
    362                            MEVENT_BUTTON, field->usage, 0);
    363                        mouse_dev->buttons[field->usage - field->usage_minimum]
    364                            = field->value;
    365                }
    366                
    367                 field = usb_hid_report_get_sibling(
    368                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    369                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    370                     USB_HID_REPORT_TYPE_INPUT);
    371         }
    372        
    373         usb_hid_report_path_free(path);
     177
     178        uint8_t butt = buffer[0];
     179        char str_buttons[4] = {
     180                butt & 1 ? '#' : '.',
     181                butt & 2 ? '#' : '.',
     182                butt & 4 ? '#' : '.',
     183                0
     184        };
     185
     186        int shift_x = ((int) buffer[1]) - 127;
     187        int shift_y = ((int) buffer[2]) - 127;
     188        int wheel = ((int) buffer[3]) - 127;
     189
     190        if (buffer[1] == 0) {
     191                shift_x = 0;
     192        }
     193        if (buffer[2] == 0) {
     194                shift_y = 0;
     195        }
     196        if (buffer[3] == 0) {
     197                wheel = 0;
     198        }
     199       
     200        if (mouse_dev->console_phone >= 0) {
     201                usb_log_debug("Console phone: %d\n", mouse_dev->console_phone);
     202                if ((shift_x != 0) || (shift_y != 0)) {
     203                        /* FIXME: guessed for QEMU */
     204                        async_req_2_0(mouse_dev->console_phone,
     205                            MEVENT_MOVE,
     206                            - shift_x / 10,  - shift_y / 10);
     207                } else {
     208                        usb_log_error("No move reported\n");
     209                }
     210                if (butt) {
     211                        /* FIXME: proper button clicking. */
     212                        async_req_2_0(mouse_dev->console_phone,
     213                            MEVENT_BUTTON, 1, 1);
     214                        async_req_2_0(mouse_dev->console_phone,
     215                            MEVENT_BUTTON, 1, 0);
     216                }
     217        } else {
     218                usb_log_error("No console phone in mouse!!\n");
     219        }
     220
     221        usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
     222            str_buttons, shift_x, shift_y, wheel);
     223
     224        /* Guess. */
     225        //async_usleep(1000);
     226        // no sleep right now
    374227
    375228        return true;
    376 }
    377 
    378 /*----------------------------------------------------------------------------*/
    379 
    380 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev)
    381 {
    382         /* Create the function exposed under /dev/devices. */
    383         usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
    384         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    385             HID_MOUSE_FUN_NAME);
    386         if (fun == NULL) {
    387                 usb_log_error("Could not create DDF function node.\n");
    388                 return ENOMEM;
    389         }
    390        
    391         /*
    392          * Store the initialized HID device and HID ops
    393          * to the DDF function.
    394          */
    395         fun->ops = &hid_dev->ops;
    396         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    397 
    398         int rc = ddf_fun_bind(fun);
    399         if (rc != EOK) {
    400                 usb_log_error("Could not bind DDF function: %s.\n",
    401                     str_error(rc));
    402                 ddf_fun_destroy(fun);
    403                 return rc;
    404         }
    405        
    406         usb_log_debug("Adding DDF function to class %s...\n",
    407             HID_MOUSE_CLASS_NAME);
    408         rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME);
    409         if (rc != EOK) {
    410                 usb_log_error(
    411                     "Could not add DDF function to class %s: %s.\n",
    412                     HID_MOUSE_CLASS_NAME, str_error(rc));
    413                 ddf_fun_destroy(fun);
    414                 return rc;
    415         }
    416        
    417         /*
    418          * Special function for acting as keyboard (wheel)
    419          */
    420         usb_log_debug("Creating DDF function %s...\n",
    421                       HID_MOUSE_WHEEL_FUN_NAME);
    422         fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    423             HID_MOUSE_WHEEL_FUN_NAME);
    424         if (fun == NULL) {
    425                 usb_log_error("Could not create DDF function node.\n");
    426                 return ENOMEM;
    427         }
    428        
    429         /*
    430          * Store the initialized HID device and HID ops
    431          * to the DDF function.
    432          */
    433         fun->ops = &hid_dev->ops;
    434         fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
    435 
    436         rc = ddf_fun_bind(fun);
    437         if (rc != EOK) {
    438                 usb_log_error("Could not bind DDF function: %s.\n",
    439                     str_error(rc));
    440                 ddf_fun_destroy(fun);
    441                 return rc;
    442         }
    443        
    444         usb_log_debug("Adding DDF function to class %s...\n",
    445             HID_MOUSE_WHEEL_CLASS_NAME);
    446         rc = ddf_fun_add_to_class(fun, HID_MOUSE_WHEEL_CLASS_NAME);
    447         if (rc != EOK) {
    448                 usb_log_error(
    449                     "Could not add DDF function to class %s: %s.\n",
    450                     HID_MOUSE_WHEEL_CLASS_NAME, str_error(rc));
    451                 ddf_fun_destroy(fun);
    452                 return rc;
    453         }
    454        
    455         return EOK;
    456229}
    457230
     
    475248        }
    476249       
    477         mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT,
    478             sizeof(int32_t));
    479        
    480         if (mouse_dev->buttons == NULL) {
    481                 usb_log_fatal("No memory!\n");
    482                 free(mouse_dev);
    483                 return ENOMEM;
    484         }
    485        
    486250        // save the Mouse device structure into the HID device structure
    487251        hid_dev->data = mouse_dev;
     
    491255       
    492256        // TODO: how to know if the device supports the request???
    493 //      usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    494 //          hid_dev->usb_dev->interface_no, IDLE_RATE);
    495        
    496         int rc = usb_mouse_create_function(hid_dev);
    497         if (rc != EOK) {
    498                 usb_mouse_free(&mouse_dev);
    499                 return rc;
    500         }
     257        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
     258            hid_dev->usb_dev->interface_no, IDLE_RATE);
    501259       
    502260        return EOK;
     
    522280                return false;
    523281        }
    524        
    525         return usb_mouse_process_report(hid_dev, buffer, buffer_size);
     282        usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
     283       
     284        return usb_mouse_process_boot_report(mouse_dev, buffer, buffer_size);
    526285}
    527286
Note: See TracChangeset for help on using the changeset viewer.