Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbhid/multimedia/multimedia.c

    r5da7199 ra0c05e7  
    6464        //int32_t *keys;
    6565        /** Count of stored keys (i.e. number of keys in the report). */
    66         //size_t key_count;     
     66        //size_t key_count;
    6767        /** IPC session to the console device (for sending key events). */
    6868        async_sess_t *console_sess;
     
    7171
    7272/*----------------------------------------------------------------------------*/
    73 /** 
     73/**
    7474 * Default handler for IPC methods not handled by DDF.
    7575 *
     
    8686{
    8787        usb_log_debug(NAME " default_connection_handler()\n");
    88        
    89         usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
    90        
    91         if (multim_dev == NULL) {
     88        if (fun == NULL || fun->driver_data == NULL) {
    9289                async_answer_0(icallid, EINVAL);
    9390                return;
    9491        }
    95        
     92
     93        usb_multimedia_t *multim_dev = fun->driver_data;
     94
    9695        async_sess_t *sess =
    9796            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     
    107106                async_answer_0(icallid, EINVAL);
    108107}
    109 
    110 /*----------------------------------------------------------------------------*/
    111 
     108/*----------------------------------------------------------------------------*/
    112109static ddf_dev_ops_t multimedia_ops = {
    113110        .default_handler = default_connection_handler
    114111};
    115 
    116112/*----------------------------------------------------------------------------*/
    117113/**
     
    125121 *       sends also these keys to application (otherwise it cannot use those
    126122 *       keys at all).
    127  * 
    128  * @param hid_dev 
    129  * @param lgtch_dev
    130  * @param type Type of the event (press / release). Recognized values: 
     123 *
     124 * @param hid_dev
     125 * @param multim_dev
     126 * @param type Type of the event (press / release). Recognized values:
    131127 *             KEY_PRESS, KEY_RELEASE
    132128 * @param key Key code of the key according to HID Usage Tables.
    133129 */
    134 static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev,
     130static void usb_multimedia_push_ev(
    135131    usb_multimedia_t *multim_dev, int type, unsigned int key)
    136132{
    137         assert(hid_dev != NULL);
    138133        assert(multim_dev != NULL);
    139        
    140         kbd_event_t ev;
    141        
    142         ev.type = type;
    143         ev.key = key;
    144         ev.mods = 0;
    145         ev.c = 0;
     134
     135        const kbd_event_t ev = {
     136                .type = type,
     137                .key = key,
     138                .mods = 0,
     139                .c = 0,
     140        };
    146141
    147142        usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
     
    151146                return;
    152147        }
    153        
     148
    154149        async_exch_t *exch = async_exchange_begin(multim_dev->console_sess);
    155         async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
    156         async_exchange_end(exch);
    157 }
    158 
    159 /*----------------------------------------------------------------------------*/
    160 
    161 static int usb_multimedia_create_function(usb_hid_dev_t *hid_dev,
    162     usb_multimedia_t *multim_dev)
    163 {
     150        if (exch != NULL) {
     151                async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
     152                async_exchange_end(exch);
     153        } else {
     154                usb_log_warning("Failed to send multimedia key.\n");
     155        }
     156}
     157/*----------------------------------------------------------------------------*/
     158int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
     159{
     160        if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
     161                return EINVAL;
     162        }
     163
     164        usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
     165
    164166        /* Create the exposed function. */
    165         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    166             NAME);
     167        ddf_fun_t *fun = ddf_fun_create(
     168            hid_dev->usb_dev->ddf_dev, fun_exposed, NAME);
    167169        if (fun == NULL) {
    168170                usb_log_error("Could not create DDF function node.\n");
    169171                return ENOMEM;
    170172        }
    171        
     173
    172174        fun->ops = &multimedia_ops;
    173         fun->driver_data = multim_dev;   // TODO: maybe change to hid_dev->data
    174        
     175
     176        usb_multimedia_t *multim_dev =
     177            ddf_fun_data_alloc(fun, sizeof(usb_multimedia_t));
     178        if (multim_dev == NULL) {
     179                ddf_fun_destroy(fun);
     180                return ENOMEM;
     181        }
     182
     183        multim_dev->console_sess = NULL;
     184
     185        //todo Autorepeat?
     186
    175187        int rc = ddf_fun_bind(fun);
    176188        if (rc != EOK) {
    177189                usb_log_error("Could not bind DDF function: %s.\n",
    178190                    str_error(rc));
    179                 // TODO: Can / should I destroy the DDF function?
    180191                ddf_fun_destroy(fun);
    181192                return rc;
    182193        }
    183        
    184         usb_log_debug("%s function created (handle: %" PRIun ").\n",
    185             NAME, fun->handle);
    186        
     194
     195        usb_log_debug(NAME " function created (handle: %" PRIun ").\n",
     196            fun->handle);
     197
    187198        rc = ddf_fun_add_to_category(fun, "keyboard");
    188199        if (rc != EOK) {
     
    190201                    "Could not add DDF function to category 'keyboard': %s.\n",
    191202                    str_error(rc));
    192                 // TODO: Can / should I destroy the DDF function?
    193                 ddf_fun_destroy(fun);
     203                if (ddf_fun_unbind(fun) != EOK) {
     204                        usb_log_error("Failed to unbind %s, won't destroy.\n",
     205                            fun->name);
     206                } else {
     207                        ddf_fun_destroy(fun);
     208                }
    194209                return rc;
    195210        }
    196        
     211
     212        /* Save the KBD device structure into the HID device structure. */
     213        *data = fun;
     214
     215        usb_log_debug(NAME " HID/multimedia structure initialized.\n");
    197216        return EOK;
    198217}
    199 
    200 /*----------------------------------------------------------------------------*/
    201 
    202 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
    203 {
    204         if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    205                 return EINVAL; /*! @todo Other return code? */
    206         }
    207        
    208         usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
    209        
    210         usb_multimedia_t *multim_dev = (usb_multimedia_t *)malloc(
    211             sizeof(usb_multimedia_t));
    212         if (multim_dev == NULL) {
    213                 return ENOMEM;
    214         }
    215        
    216         multim_dev->console_sess = NULL;
    217        
    218         /*! @todo Autorepeat */
    219        
    220         // save the KBD device structure into the HID device structure
    221         *data = multim_dev;
    222        
    223         usb_log_debug(NAME " HID/multimedia device structure initialized.\n");
    224        
    225         int rc = usb_multimedia_create_function(hid_dev, multim_dev);
    226         if (rc != EOK)
    227                 return rc;
    228        
    229         usb_log_debug(NAME " HID/multimedia structure initialized.\n");
    230        
    231         return EOK;
    232 }
    233 
    234 /*----------------------------------------------------------------------------*/
    235 
     218/*----------------------------------------------------------------------------*/
    236219void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
    237220{
    238         if (hid_dev == NULL) {
    239                 return;
    240         }
    241        
    242         if (data != NULL) {
    243                 usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
    244                 // hangup session to the console
    245                 async_hangup(multim_dev->console_sess);
    246         }
    247 }
    248 
    249 /*----------------------------------------------------------------------------*/
    250 
     221        ddf_fun_t *fun = data;
     222        if (fun != NULL && fun->driver_data != NULL) {
     223                usb_multimedia_t *multim_dev = fun->driver_data;
     224                /* Hangup session to the console */
     225                if (multim_dev->console_sess)
     226                        async_hangup(multim_dev->console_sess);
     227                if (ddf_fun_unbind(fun) != EOK) {
     228                        usb_log_error("Failed to unbind %s, won't destroy.\n",
     229                            fun->name);
     230                } else {
     231                        usb_log_debug2("%s unbound.\n", fun->name);
     232                        /* This frees multim_dev too as it was stored in
     233                         * fun->data */
     234                        ddf_fun_destroy(fun);
     235                }
     236        } else {
     237                usb_log_error(
     238                    "Failed to deinit multimedia subdriver, data missing.\n");
     239        }
     240}
     241/*----------------------------------------------------------------------------*/
    251242bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
    252243{
    253244        // TODO: checks
    254         if (hid_dev == NULL || data == NULL) {
     245        ddf_fun_t *fun = data;
     246        if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) {
    255247                return false;
    256248        }
    257249
    258         usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
    259        
     250        usb_multimedia_t *multim_dev = fun->driver_data;
     251
    260252        usb_hid_report_path_t *path = usb_hid_report_path();
    261         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     253        if (path == NULL)
     254                return true; /* This might be a temporary failure. */
     255
     256        int ret =
     257            usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     258        if (ret != EOK) {
     259                usb_hid_report_path_free(path);
     260                return true; /* This might be a temporary failure. */
     261        }
    262262
    263263        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
    264264
    265265        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    266             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    267             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     266            &hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
     267            | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    268268            USB_HID_REPORT_TYPE_INPUT);
    269269
    270         /*! @todo Is this iterating OK if done multiple times?
    271          *  @todo The parsing is not OK
    272          */
     270        //FIXME Is this iterating OK if done multiple times?
     271        //FIXME The parsing is not OK. (what's wrong?)
    273272        while (field != NULL) {
    274                 if(field->value != 0) {
    275                         usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
     273                if (field->value != 0) {
     274                        usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n",
    276275                            field->value, field->usage);
    277                         unsigned int key =
     276                        const unsigned key =
    278277                            usb_multimedia_map_usage(field->usage);
    279                         const char *key_str = 
     278                        const char *key_str =
    280279                            usbhid_multimedia_usage_to_str(field->usage);
    281280                        usb_log_info("Pressed key: %s\n", key_str);
    282                         usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS,
    283                                                key);
     281                        usb_multimedia_push_ev(multim_dev, KEY_PRESS, key);
    284282                }
    285                
     283
    286284                field = usb_hid_report_get_sibling(
    287                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    288                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     285                    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
     286                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    289287                    USB_HID_REPORT_TYPE_INPUT);
    290         }       
     288        }
    291289
    292290        usb_hid_report_path_free(path);
    293        
     291
    294292        return true;
    295293}
    296 
    297294/**
    298295 * @}
Note: See TracChangeset for help on using the changeset viewer.