Changeset a81a1d09 in mainline for uspace/drv/usbhid/mouse/mousedev.c


Ignore:
Timestamp:
2011-05-11T16:49:28Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
19387b61
Parents:
e1dbcbc (diff), 9212f8a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge development/ changes

File:
1 edited

Legend:

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

    re1dbcbc ra81a1d09  
    3939#include <usb/classes/hid.h>
    4040#include <usb/classes/hidreq.h>
     41#include <usb/classes/hidut.h>
    4142#include <errno.h>
    4243#include <str_error.h>
    4344#include <ipc/mouse.h>
     45#include <io/console.h>
     46
     47#include <ipc/kbd.h>
     48#include <io/keycode.h>
    4449
    4550#include "mousedev.h"
    4651#include "../usbhid.h"
     52
     53#define NAME "mouse"
    4754
    4855/*----------------------------------------------------------------------------*/
     
    5865
    5966const char *HID_MOUSE_FUN_NAME = "mouse";
     67const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
    6068const char *HID_MOUSE_CLASS_NAME = "mouse";
     69const char *HID_MOUSE_WHEEL_CLASS_NAME = "keyboard";
    6170
    6271/** Default idle rate for mouses. */
    6372static const uint8_t IDLE_RATE = 0;
     73static const size_t USB_MOUSE_BUTTON_COUNT = 3;
    6474
    6575/*----------------------------------------------------------------------------*/
     
    115125       
    116126        if (hid_dev == NULL || hid_dev->data == NULL) {
     127                usb_log_debug("default_connection_handler: Missing "
     128                    "parameters.\n");
    117129                async_answer_0(icallid, EINVAL);
    118130                return;
     
    123135        usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
    124136       
     137        int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0)
     138                     ? &mouse_dev->mouse_phone : &mouse_dev->wheel_phone;
     139       
    125140        if (method == IPC_M_CONNECT_TO_ME) {
    126141                int callback = IPC_GET_ARG5(*icall);
    127142
    128                 if (mouse_dev->console_phone != -1) {
     143                if (*phone != -1) {
     144                        usb_log_debug("default_connection_handler: Console "
     145                            "phone to mouse already set.\n");
    129146                        async_answer_0(icallid, ELIMIT);
     147                        //async_answer_0(icallid, EOK);
    130148                        return;
    131149                }
    132150
    133                 mouse_dev->console_phone = callback;
     151                *phone = callback;
    134152                usb_log_debug("Console phone to mouse set ok (%d).\n", callback);
    135153                async_answer_0(icallid, EOK);
     
    137155        }
    138156
     157        usb_log_debug("default_connection_handler: Invalid function.\n");
    139158        async_answer_0(icallid, EINVAL);
    140159}
     
    148167                return NULL;
    149168        }
    150         mouse->console_phone = -1;
     169        mouse->mouse_phone = -1;
     170        mouse->wheel_phone = -1;
    151171       
    152172        return mouse;
     
    160180       
    161181        // hangup phone to the console
    162         if ((*mouse_dev)->console_phone >= 0) {
    163                 async_hangup((*mouse_dev)->console_phone);
     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);
    164188        }
    165189       
     
    170194/*----------------------------------------------------------------------------*/
    171195
    172 static bool usb_mouse_process_boot_report(usb_mouse_t *mouse_dev,
    173     uint8_t *buffer, size_t buffer_size)
    174 {
     196static 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
     226static 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       
    175231        usb_log_debug2("got buffer: %s.\n",
    176232            usb_debug_str_buffer(buffer, buffer_size, 0));
    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
     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);
    227374
    228375        return true;
     376}
     377
     378/*----------------------------------------------------------------------------*/
     379
     380static 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;
    229456}
    230457
     
    248475        }
    249476       
     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       
    250486        // save the Mouse device structure into the HID device structure
    251487        hid_dev->data = mouse_dev;
     
    255491       
    256492        // TODO: how to know if the device supports the request???
    257         usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    258             hid_dev->usb_dev->interface_no, IDLE_RATE);
     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        }
    259501       
    260502        return EOK;
     
    280522                return false;
    281523        }
    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);
     524       
     525        return usb_mouse_process_report(hid_dev, buffer, buffer_size);
    285526}
    286527
Note: See TracChangeset for help on using the changeset viewer.