ipc_dev.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 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 <errno.h>
00036 #include <str.h>
00037 #include <stdio.h>
00038 #include <assert.h>
00039 #include <async.h>
00040 #include <devman.h>
00041 #include <usbvirt/device.h>
00042 #include <usbvirt/ipc.h>
00043 #include <usb/debug.h>
00044 
00051 static void ipc_get_name(usbvirt_device_t *dev,
00052     ipc_callid_t iid, ipc_call_t *icall)
00053 {
00054         if (dev->name == NULL) {
00055                 async_answer_0(iid, ENOENT);
00056         }
00057 
00058         size_t size = str_size(dev->name);
00059 
00060         ipc_callid_t callid;
00061         size_t accepted_size;
00062         if (!async_data_read_receive(&callid, &accepted_size)) {
00063                 async_answer_0(iid, EINVAL);
00064                 return;
00065         }
00066 
00067         if (accepted_size > size) {
00068                 accepted_size = size;
00069         }
00070         async_data_read_finalize(callid, dev->name, accepted_size);
00071 
00072         async_answer_1(iid, EOK, accepted_size);
00073 }
00074 
00081 static void ipc_control_read(usbvirt_device_t *dev,
00082     ipc_callid_t iid, ipc_call_t *icall)
00083 {
00084         int rc;
00085 
00086         void *setup_packet = NULL;
00087         size_t setup_packet_len = 0;
00088         size_t data_len = 0;
00089 
00090         rc = async_data_write_accept(&setup_packet, false,
00091             1, 1024, 0, &setup_packet_len);
00092         if (rc != EOK) {
00093                 async_answer_0(iid, rc);
00094                 return;
00095         }
00096 
00097         ipc_callid_t data_callid;
00098         if (!async_data_read_receive(&data_callid, &data_len)) {
00099                 async_answer_0(iid, EPARTY);
00100                 free(setup_packet);
00101                 return;
00102         }
00103 
00104         void *buffer = malloc(data_len);
00105         if (buffer == NULL) {
00106                 async_answer_0(iid, ENOMEM);
00107                 free(setup_packet);
00108                 return;
00109         }
00110 
00111         size_t actual_len;
00112         rc = usbvirt_control_read(dev, setup_packet, setup_packet_len,
00113             buffer, data_len, &actual_len);
00114 
00115         if (rc != EOK) {
00116                 async_answer_0(data_callid, rc);
00117                 async_answer_0(iid, rc);
00118                 free(setup_packet);
00119                 free(buffer);
00120                 return;
00121         }
00122 
00123         async_data_read_finalize(data_callid, buffer, actual_len);
00124         async_answer_0(iid, EOK);
00125 
00126         free(setup_packet);
00127         free(buffer);
00128 }
00129 
00136 static void ipc_control_write(usbvirt_device_t *dev,
00137     ipc_callid_t iid, ipc_call_t *icall)
00138 {
00139         size_t data_buffer_len = IPC_GET_ARG1(*icall);
00140         int rc;
00141 
00142         void *setup_packet = NULL;
00143         void *data_buffer = NULL;
00144         size_t setup_packet_len = 0;
00145 
00146         rc = async_data_write_accept(&setup_packet, false,
00147             1, 0, 0, &setup_packet_len);
00148         if (rc != EOK) {
00149                 async_answer_0(iid, rc);
00150                 return;
00151         }
00152 
00153         if (data_buffer_len > 0) {
00154                 rc = async_data_write_accept(&data_buffer, false,
00155                     1, 0, 0, &data_buffer_len);
00156                 if (rc != EOK) {
00157                         async_answer_0(iid, rc);
00158                         free(setup_packet);
00159                         return;
00160                 }
00161         }
00162 
00163         rc = usbvirt_control_write(dev, setup_packet, setup_packet_len,
00164             data_buffer, data_buffer_len);
00165 
00166         async_answer_0(iid, rc);
00167 
00168         free(setup_packet);
00169         if (data_buffer != NULL) {
00170                 free(data_buffer);
00171         }
00172 }
00173 
00180 static void ipc_data_in(usbvirt_device_t *dev,
00181     usb_transfer_type_t transfer_type,
00182     ipc_callid_t iid, ipc_call_t *icall)
00183 {
00184         usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
00185 
00186         int rc;
00187 
00188         size_t data_len = 0;
00189         ipc_callid_t data_callid;
00190         if (!async_data_read_receive(&data_callid, &data_len)) {
00191                 async_answer_0(iid, EPARTY);
00192                 return;
00193         }
00194 
00195         void *buffer = malloc(data_len);
00196         if (buffer == NULL) {
00197                 async_answer_0(iid, ENOMEM);
00198                 return;
00199         }
00200 
00201         size_t actual_len;
00202         rc = usbvirt_data_in(dev, transfer_type, endpoint,
00203             buffer, data_len, &actual_len);
00204 
00205         if (rc != EOK) {
00206                 async_answer_0(data_callid, rc);
00207                 async_answer_0(iid, rc);
00208                 free(buffer);
00209                 return;
00210         }
00211 
00212         async_data_read_finalize(data_callid, buffer, actual_len);
00213         async_answer_0(iid, EOK);
00214 
00215         free(buffer);
00216 }
00217 
00224 static void ipc_data_out(usbvirt_device_t *dev,
00225     usb_transfer_type_t transfer_type,
00226     ipc_callid_t iid, ipc_call_t *icall)
00227 {
00228         usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
00229 
00230         void *data_buffer = NULL;
00231         size_t data_buffer_size = 0;
00232 
00233         int rc = async_data_write_accept(&data_buffer, false,
00234             1, 0, 0, &data_buffer_size);
00235         if (rc != EOK) {
00236                 async_answer_0(iid, rc);
00237                 return;
00238         }
00239 
00240         rc = usbvirt_data_out(dev, transfer_type, endpoint,
00241             data_buffer, data_buffer_size);
00242 
00243         async_answer_0(iid, rc);
00244 
00245         free(data_buffer);
00246 }
00247 
00255 bool usbvirt_ipc_handle_call(usbvirt_device_t *dev,
00256     ipc_callid_t callid, ipc_call_t *call)
00257 {
00258         switch (IPC_GET_IMETHOD(*call)) {
00259         case IPC_M_USBVIRT_GET_NAME:
00260                 ipc_get_name(dev, callid, call);
00261                 break;
00262 
00263         case IPC_M_USBVIRT_CONTROL_READ:
00264                 ipc_control_read(dev, callid, call);
00265                 break;
00266 
00267         case IPC_M_USBVIRT_CONTROL_WRITE:
00268                 ipc_control_write(dev, callid, call);
00269                 break;
00270 
00271         case IPC_M_USBVIRT_INTERRUPT_IN:
00272                 ipc_data_in(dev, USB_TRANSFER_INTERRUPT, callid, call);
00273                 break;
00274 
00275         case IPC_M_USBVIRT_BULK_IN:
00276                 ipc_data_in(dev, USB_TRANSFER_BULK, callid, call);
00277                 break;
00278 
00279         case IPC_M_USBVIRT_INTERRUPT_OUT:
00280                 ipc_data_out(dev, USB_TRANSFER_INTERRUPT, callid, call);
00281                 break;
00282 
00283         case IPC_M_USBVIRT_BULK_OUT:
00284                 ipc_data_out(dev, USB_TRANSFER_BULK, callid, call);
00285                 break;
00286 
00287 
00288         default:
00289                 return false;
00290         }
00291 
00292         return true;
00293 }
00294 

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