hiddev.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Lubos Slovak
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 
00037 #include <usb/debug.h>
00038 #include <usb/classes/classes.h>
00039 #include <errno.h>
00040 #include <str_error.h>
00041 #include <bool.h>
00042 
00043 #include <usbhid_iface.h>
00044 
00045 #include "hiddev.h"
00046 #include "usbhid.h"
00047 
00048 /*----------------------------------------------------------------------------*/
00049 
00050 usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
00051         .transfer_type = USB_TRANSFER_INTERRUPT,
00052         .direction = USB_DIRECTION_IN,
00053         .interface_class = USB_CLASS_HID,
00054         .flags = 0
00055 };
00056 
00057 const char *HID_GENERIC_FUN_NAME = "hid";
00058 const char *HID_GENERIC_CLASS_NAME = "hid";
00059 
00060 /*----------------------------------------------------------------------------*/
00061 
00062 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
00063 
00064 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
00065     size_t size, size_t *act_size, int *event_nr, unsigned int flags);
00066 
00067 static int usb_generic_hid_client_connected(ddf_fun_t *fun);
00068 
00069 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun);
00070 
00071 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
00072     size_t size, size_t *actual_size);
00073 
00074 /*----------------------------------------------------------------------------*/
00075 
00076 static usbhid_iface_t usb_generic_iface = {
00077         .get_event = usb_generic_hid_get_event,
00078         .get_event_length = usb_generic_hid_get_event_length,
00079         .get_report_descriptor_length = usb_generic_get_report_descriptor_length,
00080         .get_report_descriptor = usb_generic_get_report_descriptor
00081 };
00082 
00083 static ddf_dev_ops_t usb_generic_hid_ops = {
00084         .interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
00085         .open = usb_generic_hid_client_connected
00086 };
00087 
00088 /*----------------------------------------------------------------------------*/
00089 
00090 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
00091 {
00092         usb_log_debug2("Generic HID: Get event length (fun: %p, "
00093             "fun->driver_data: %p.\n", fun, fun->driver_data);
00094         
00095         if (fun == NULL || fun->driver_data == NULL) {
00096                 return 0;
00097         }
00098 
00099         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
00100         
00101         usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
00102             hid_dev, hid_dev->max_input_report_size);
00103         
00104         return hid_dev->max_input_report_size;
00105 }
00106 
00107 /*----------------------------------------------------------------------------*/
00108 
00109 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
00110     size_t size, size_t *act_size, int *event_nr, unsigned int flags)
00111 {
00112         usb_log_debug2("Generic HID: Get event.\n");
00113         
00114         if (fun == NULL || fun->driver_data == NULL || buffer == NULL
00115             || act_size == NULL || event_nr == NULL) {
00116                 usb_log_debug("No function");
00117                 return EINVAL;
00118         }
00119 
00120         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
00121         
00122         if (hid_dev->input_report_size > size) {
00123                 usb_log_debug("input_report_size > size (%zu, %zu)\n", 
00124                     hid_dev->input_report_size, size);
00125                 return EINVAL;  // TODO: other error code
00126         }
00127         
00129         memcpy(buffer, hid_dev->input_report, 
00130             hid_dev->input_report_size);
00131         *act_size = hid_dev->input_report_size;
00132         *event_nr = usb_hid_report_number(hid_dev);
00133         
00134         usb_log_debug2("OK\n");
00135         
00136         return EOK;
00137 }
00138 
00139 /*----------------------------------------------------------------------------*/
00140 
00141 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
00142 {
00143         usb_log_debug("Generic HID: Get report descriptor length.\n");
00144         
00145         if (fun == NULL || fun->driver_data == NULL) {
00146                 usb_log_debug("No function");
00147                 return EINVAL;
00148         }
00149         
00150         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
00151         
00152         usb_log_debug2("hid_dev->report_desc_size = %zu\n", 
00153             hid_dev->report_desc_size);
00154         
00155         return hid_dev->report_desc_size;
00156 }
00157 
00158 /*----------------------------------------------------------------------------*/
00159 
00160 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
00161     size_t size, size_t *actual_size)
00162 {
00163         usb_log_debug2("Generic HID: Get report descriptor.\n");
00164         
00165         if (fun == NULL || fun->driver_data == NULL) {
00166                 usb_log_debug("No function");
00167                 return EINVAL;
00168         }
00169         
00170         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
00171         
00172         if (hid_dev->report_desc_size > size) {
00173                 return EINVAL;
00174         }
00175         
00176         memcpy(desc, hid_dev->report_desc, hid_dev->report_desc_size);
00177         *actual_size = hid_dev->report_desc_size;
00178         
00179         return EOK;
00180 }
00181 
00182 /*----------------------------------------------------------------------------*/
00183 
00184 static int usb_generic_hid_client_connected(ddf_fun_t *fun)
00185 {
00186         usb_log_debug("Generic HID: Client connected.\n");
00187         return EOK;
00188 }
00189 
00190 /*----------------------------------------------------------------------------*/
00191 
00192 static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
00193 {       
00194         /* Create the function exposed under /dev/devices. */
00196         usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
00197         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
00198             HID_GENERIC_FUN_NAME);
00199         if (fun == NULL) {
00200                 usb_log_error("Could not create DDF function node.\n");
00201                 return ENOMEM;
00202         }
00203         
00204         fun->ops = &usb_generic_hid_ops;
00205         fun->driver_data = hid_dev;
00206 
00207         int rc = ddf_fun_bind(fun);
00208         if (rc != EOK) {
00209                 usb_log_error("Could not bind DDF function: %s.\n",
00210                     str_error(rc));
00211                 ddf_fun_destroy(fun);
00212                 return rc;
00213         }
00214         
00215         usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
00216         
00217         return EOK;
00218 }
00219 
00220 /*----------------------------------------------------------------------------*/
00221 
00222 int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
00223 {
00224         if (hid_dev == NULL) {
00225                 return EINVAL;
00226         }
00227         
00228         return usb_generic_hid_create_function(hid_dev);
00229 }
00230 
00231 /*----------------------------------------------------------------------------*/
00232 
00233 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data/*, 
00234     uint8_t *buffer, size_t buffer_size*/)
00235 {
00236 //      usb_log_debug2("usb_hid_polling_callback(%p, %p, %zu)\n",
00237 //          hid_dev, buffer, buffer_size);
00238 //      usb_debug_str_buffer(buffer, buffer_size, 0);
00239         return true;
00240 }
00241 

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