00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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