remote_usbhid.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010-2011 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 
00035 #include <async.h>
00036 #include <errno.h>
00037 #include <assert.h>
00038 #include <stdio.h>
00039 
00040 #include "usbhid_iface.h"
00041 #include "ddf/driver.h"
00042 
00043 static void remote_usbhid_get_event_length(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
00044 static void remote_usbhid_get_event(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
00045 static void remote_usbhid_get_report_descriptor_length(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
00046 static void remote_usbhid_get_report_descriptor(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
00047 // static void remote_usbhid_(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
00048 
00050 static remote_iface_func_ptr_t remote_usbhid_iface_ops [] = {
00051         remote_usbhid_get_event_length,
00052         remote_usbhid_get_event,
00053         remote_usbhid_get_report_descriptor_length,
00054         remote_usbhid_get_report_descriptor
00055 };
00056 
00059 remote_iface_t remote_usbhid_iface = {
00060         .method_count = sizeof(remote_usbhid_iface_ops) /
00061             sizeof(remote_usbhid_iface_ops[0]),
00062         .methods = remote_usbhid_iface_ops
00063 };
00064 
00065 //usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
00066 
00067 
00068 void remote_usbhid_get_event_length(ddf_fun_t *fun, void *iface,
00069     ipc_callid_t callid, ipc_call_t *call)
00070 {
00071         printf("remote_usbhid_get_event_length()\n");
00072         
00073         usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
00074 
00075         if (!hid_iface->get_event_length) {
00076                 printf("Get event length not set!\n");
00077                 async_answer_0(callid, ENOTSUP);
00078                 return;
00079         }
00080 
00081         size_t len = hid_iface->get_event_length(fun);
00082 //      if (len == 0) {
00083 //              len = EEMPTY;
00084 //      }
00085         async_answer_1(callid, EOK, len);
00086         
00087 //      if (len < 0) {
00088 //              async_answer_0(callid, len);
00089 //      } else {
00090 //              async_answer_1(callid, EOK, len);
00091 //      }
00092 }
00093 
00094 void remote_usbhid_get_event(ddf_fun_t *fun, void *iface,
00095     ipc_callid_t callid, ipc_call_t *call)
00096 {
00097         usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
00098 
00099         if (!hid_iface->get_event) {
00100                 async_answer_0(callid, ENOTSUP);
00101                 return;
00102         }
00103 
00104         unsigned int flags = DEV_IPC_GET_ARG1(*call);
00105 
00106         size_t len;
00107         ipc_callid_t data_callid;
00108         if (!async_data_read_receive(&data_callid, &len)) {
00109                 async_answer_0(callid, EPARTY);
00110                 return;
00111         }
00112 //      /* Check that length is even number. Truncate otherwise. */
00113 //      if ((len % 2) == 1) {
00114 //              len--;
00115 //      }
00116         if (len == 0) {
00117                 async_answer_0(data_callid, EINVAL);
00118                 async_answer_0(callid, EINVAL);
00119                 return;
00120         }
00121 
00122         int rc;
00123 
00124         uint8_t *data = malloc(len);
00125         if (data == NULL) {
00126                 async_answer_0(data_callid, ENOMEM);
00127                 async_answer_0(callid, ENOMEM);
00128                 return;
00129         }
00130 
00131         size_t act_length;
00132         int event_nr;
00133         rc = hid_iface->get_event(fun, data, len, &act_length, &event_nr, flags);
00134         if (rc != EOK) {
00135                 free(data);
00136                 async_answer_0(data_callid, rc);
00137                 async_answer_0(callid, rc);
00138                 return;
00139         }
00140         if (act_length >= len) {
00141                 /* This shall not happen. */
00142                 // FIXME: how about an assert here?
00143                 act_length = len;
00144         }
00145 
00146         async_data_read_finalize(data_callid, data, act_length);
00147 
00148         free(data);
00149 
00150         async_answer_1(callid, EOK, event_nr);
00151 }
00152 
00153 void remote_usbhid_get_report_descriptor_length(ddf_fun_t *fun, void *iface,
00154     ipc_callid_t callid, ipc_call_t *call)
00155 {
00156         usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
00157 
00158         if (!hid_iface->get_report_descriptor_length) {
00159                 async_answer_0(callid, ENOTSUP);
00160                 return;
00161         }
00162 
00163         size_t len = hid_iface->get_report_descriptor_length(fun);
00164         async_answer_1(callid, EOK, (sysarg_t) len);
00165 }
00166 
00167 void remote_usbhid_get_report_descriptor(ddf_fun_t *fun, void *iface,
00168     ipc_callid_t callid, ipc_call_t *call)
00169 {
00170         usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
00171 
00172         if (!hid_iface->get_report_descriptor) {
00173                 async_answer_0(callid, ENOTSUP);
00174                 return;
00175         }
00176 
00177         size_t len;
00178         ipc_callid_t data_callid;
00179         if (!async_data_read_receive(&data_callid, &len)) {
00180                 async_answer_0(callid, EINVAL);
00181                 return;
00182         }
00183 
00184         if (len == 0) {
00185                 async_answer_0(data_callid, EINVAL);
00186                 async_answer_0(callid, EINVAL);
00187                 return;
00188         }
00189 
00190         uint8_t *descriptor = malloc(len);
00191         if (descriptor == NULL) {
00192                 async_answer_0(data_callid, ENOMEM);
00193                 async_answer_0(callid, ENOMEM);
00194                 return;
00195         }
00196 
00197         size_t act_len = 0;
00198         int rc = hid_iface->get_report_descriptor(fun, descriptor, len,
00199             &act_len);
00200         if (act_len > len) {
00201                 rc = ELIMIT;
00202         }
00203         if (rc != EOK) {
00204                 free(descriptor);
00205                 async_answer_0(data_callid, rc);
00206                 async_answer_0(callid, rc);
00207                 return;
00208         }
00209 
00210         async_data_read_finalize(data_callid, descriptor, act_len);
00211         async_answer_0(callid, EOK);
00212 
00213         free(descriptor);
00214 }
00215 
00216 
00217 

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