multimedia.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include "multimedia.h"
00039 #include "../usbhid.h"
00040 #include "keymap.h"
00041 
00042 #include <usb/hid/hidparser.h>
00043 #include <usb/debug.h>
00044 #include <usb/hid/usages/core.h>
00045 #include <usb/hid/usages/consumer.h>
00046 
00047 #include <errno.h>
00048 #include <str_error.h>
00049 
00050 #include <ipc/kbd.h>
00051 #include <io/console.h>
00052 
00053 #define NAME "multimedia-keys"
00054 
00055 /*----------------------------------------------------------------------------*/
00059 typedef struct usb_multimedia_t {
00061         //int32_t *keys_old;
00063         //int32_t *keys;
00065         //size_t key_count;     
00067         int console_phone;
00068 } usb_multimedia_t;
00069 
00070 
00071 /*----------------------------------------------------------------------------*/
00083 static void default_connection_handler(ddf_fun_t *fun,
00084     ipc_callid_t icallid, ipc_call_t *icall)
00085 {
00086         usb_log_debug(NAME " default_connection_handler()\n");
00087         
00088         sysarg_t method = IPC_GET_IMETHOD(*icall);
00089         
00090         usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
00091         //usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
00092         
00093         if (multim_dev == NULL) {
00094                 async_answer_0(icallid, EINVAL);
00095                 return;
00096         }
00097 
00098         if (method == IPC_M_CONNECT_TO_ME) {
00099                 int callback = IPC_GET_ARG5(*icall);
00100 
00101                 if (multim_dev->console_phone != -1) {
00102                         async_answer_0(icallid, ELIMIT);
00103                         return;
00104                 }
00105 
00106                 multim_dev->console_phone = callback;
00107                 usb_log_debug(NAME " Saved phone to console: %d\n", callback);
00108                 async_answer_0(icallid, EOK);
00109                 return;
00110         }
00111         
00112         async_answer_0(icallid, EINVAL);
00113 }
00114 
00115 /*----------------------------------------------------------------------------*/
00116 
00117 static ddf_dev_ops_t multimedia_ops = {
00118         .default_handler = default_connection_handler
00119 };
00120 
00121 /*----------------------------------------------------------------------------*/
00139 static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev, 
00140     usb_multimedia_t *multim_dev, int type, unsigned int key)
00141 {
00142         assert(hid_dev != NULL);
00143         assert(multim_dev != NULL);
00144         
00145         console_event_t ev;
00146         
00147         ev.type = type;
00148         ev.key = key;
00149         ev.mods = 0;
00150         ev.c = 0;
00151 
00152         usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
00153         if (multim_dev->console_phone < 0) {
00154                 usb_log_warning(
00155                     "Connection to console not ready, key discarded.\n");
00156                 return;
00157         }
00158         
00159         async_msg_4(multim_dev->console_phone, KBD_EVENT, ev.type, ev.key, 
00160             ev.mods, ev.c);
00161 }
00162 
00163 /*----------------------------------------------------------------------------*/
00164 
00165 static void usb_multimedia_free(usb_multimedia_t **multim_dev)
00166 {
00167         if (multim_dev == NULL || *multim_dev == NULL) {
00168                 return;
00169         }
00170         
00171         // hangup phone to the console
00172         async_hangup((*multim_dev)->console_phone);
00173 
00174         free(*multim_dev);
00175         *multim_dev = NULL;
00176 }
00177 
00178 /*----------------------------------------------------------------------------*/
00179 
00180 static int usb_multimedia_create_function(usb_hid_dev_t *hid_dev, 
00181     usb_multimedia_t *multim_dev)
00182 {
00183         /* Create the function exposed under /dev/devices. */
00184         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
00185             NAME);
00186         if (fun == NULL) {
00187                 usb_log_error("Could not create DDF function node.\n");
00188                 return ENOMEM;
00189         }
00190         
00191         fun->ops = &multimedia_ops;
00192         fun->driver_data = multim_dev;   // TODO: maybe change to hid_dev->data
00193         
00194         int rc = ddf_fun_bind(fun);
00195         if (rc != EOK) {
00196                 usb_log_error("Could not bind DDF function: %s.\n",
00197                     str_error(rc));
00198                 // TODO: Can / should I destroy the DDF function?
00199                 ddf_fun_destroy(fun);
00200                 return rc;
00201         }
00202         
00203         usb_log_debug("%s function created (jandle: %" PRIun ").\n",
00204             NAME, fun->handle);
00205         
00206         rc = ddf_fun_add_to_class(fun, "keyboard");
00207         if (rc != EOK) {
00208                 usb_log_error(
00209                     "Could not add DDF function to class 'keyboard': %s.\n",
00210                     str_error(rc));
00211                 // TODO: Can / should I destroy the DDF function?
00212                 ddf_fun_destroy(fun);
00213                 return rc;
00214         }
00215         
00216         return EOK;
00217 }
00218 
00219 /*----------------------------------------------------------------------------*/
00220 
00221 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
00222 {
00223         if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
00224                 return EINVAL; 
00225         }
00226         
00227         usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
00228         
00229         usb_multimedia_t *multim_dev = (usb_multimedia_t *)malloc(
00230             sizeof(usb_multimedia_t));
00231         if (multim_dev == NULL) {
00232                 return ENOMEM;
00233         }
00234         
00235         multim_dev->console_phone = -1;
00236         
00239         // save the KBD device structure into the HID device structure
00240         *data = multim_dev;
00241         
00242         usb_log_debug(NAME " HID/multimedia device structure initialized.\n");
00243         
00244         int rc = usb_multimedia_create_function(hid_dev, multim_dev);
00245         if (rc != EOK) {
00246                 usb_multimedia_free(&multim_dev);
00247                 return rc;
00248         }
00249         
00250         usb_log_debug(NAME " HID/multimedia structure initialized.\n");
00251         
00252         return EOK;
00253 }
00254 
00255 /*----------------------------------------------------------------------------*/
00256 
00257 void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
00258 {
00259         if (hid_dev == NULL) {
00260                 return;
00261         }
00262         
00263         if (data != NULL) {
00264                 usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
00265                 usb_multimedia_free(&multim_dev);
00266         }
00267 }
00268 
00269 /*----------------------------------------------------------------------------*/
00270 
00271 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data/*, 
00272     uint8_t *buffer, size_t buffer_size*/)
00273 {
00274         // TODO: checks
00275         if (hid_dev == NULL || data == NULL/* || buffer == NULL*/) {
00276                 return false;
00277         }
00278         
00279 //      usb_log_debug(NAME " usb_lgtch_polling_callback(%p, %p, %zu)\n",
00280 //          hid_dev, buffer, buffer_size);
00281         
00282         usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
00283 
00284 //      usb_log_debug(NAME " Calling usb_hid_parse_report() with "
00285 //          "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
00286         
00287         usb_hid_report_path_t *path = usb_hid_report_path();
00288         usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
00289 
00290 //      uint8_t report_id;
00291         
00292 //      int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 
00293 //          &report_id);
00294         
00295 //      if (rc != EOK) {
00296 //              usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 
00297 //                  str_error(rc));
00298 //              return true;
00299 //      }
00300         
00301         usb_hid_report_path_set_report_id(path, hid_dev->report_id);
00302 
00303         usb_hid_report_field_t *field = usb_hid_report_get_sibling(
00304             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END 
00305             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
00306             USB_HID_REPORT_TYPE_INPUT);
00307 
00311         while (field != NULL) {
00312                 if(field->value != 0) {
00313                         usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
00314                             field->value, field->usage);
00315                         unsigned int key = 
00316                             usb_multimedia_map_usage(field->usage);
00317                         const char *key_str = 
00318                             usbhid_multimedia_usage_to_str(field->usage);
00319                         usb_log_info("Pressed key: %s\n", key_str);
00320                         usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS, 
00321                                                key);
00322                 }
00323                 
00324                 field = usb_hid_report_get_sibling(
00325                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
00326                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
00327                     USB_HID_REPORT_TYPE_INPUT);
00328         }       
00329 
00330         usb_hid_report_path_free(path);
00331         
00332         return true;
00333 }
00334 

Generated on Thu Jun 2 07:45:44 2011 for HelenOS/USB by  doxygen 1.4.7