Changeset 19a1800 in mainline for uspace/lib/drv/generic/remote_usbhc.c
- Timestamp:
- 2011-03-01T22:20:56Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e24e7b1
- Parents:
- 976f546 (diff), ac8285d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
uspace/lib/drv/generic/remote_usbhc.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
r976f546 r19a1800 1 1 /* 2 * Copyright (c) 2010 Vojtech Horky2 * Copyright (c) 2010-2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 33 33 */ 34 34 35 #include <ipc/ipc.h>36 35 #include <async.h> 37 36 #include <errno.h> 37 #include <assert.h> 38 38 39 39 #include "usbhc_iface.h" 40 #include "d river.h"40 #include "ddf/driver.h" 41 41 42 42 #define USB_MAX_PAYLOAD_SIZE 1020 43 44 static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 45 static void remote_usbhc_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *); 46 static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *); 47 static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_control_write_setup(device_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_control_write_data(device_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_write_status(device_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_control_read_setup(device_t *, void *, ipc_callid_t, ipc_call_t *); 52 static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *); 53 static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *); 54 static void remote_usbhc_reserve_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 55 static void remote_usbhc_release_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 56 static void remote_usbhc_request_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 57 static void remote_usbhc_bind_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 58 static void remote_usbhc_release_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 59 //static void remote_usbhc(device_t *, void *, ipc_callid_t, ipc_call_t *); 43 #define HACK_MAX_PACKET_SIZE 8 44 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4 45 46 static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 47 static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 52 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 54 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 55 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 56 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 60 58 61 59 /** Remote USB host controller interface operations. */ 62 60 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 63 remote_usbhc_get_address,64 65 remote_usbhc_get_buffer,66 67 61 remote_usbhc_reserve_default_address, 68 62 remote_usbhc_release_default_address, … … 75 69 remote_usbhc_interrupt_in, 76 70 77 remote_usbhc_control_write_setup, 78 remote_usbhc_control_write_data, 79 remote_usbhc_control_write_status, 80 81 remote_usbhc_control_read_setup, 82 remote_usbhc_control_read_data, 83 remote_usbhc_control_read_status 71 remote_usbhc_bulk_out, 72 remote_usbhc_bulk_in, 73 74 remote_usbhc_control_write, 75 remote_usbhc_control_read 84 76 }; 85 77 … … 94 86 typedef struct { 95 87 ipc_callid_t caller; 88 ipc_callid_t data_caller; 96 89 void *buffer; 90 void *setup_packet; 97 91 size_t size; 98 92 } async_transaction_t; 99 93 100 void remote_usbhc_get_address(device_t *device, void *iface, 101 ipc_callid_t callid, ipc_call_t *call) 102 { 103 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 104 105 if (!usb_iface->tell_address) { 106 ipc_answer_0(callid, ENOTSUP); 107 return; 108 } 109 110 devman_handle_t handle = DEV_IPC_GET_ARG1(*call); 94 static void async_transaction_destroy(async_transaction_t *trans) 95 { 96 if (trans == NULL) { 97 return; 98 } 99 100 if (trans->setup_packet != NULL) { 101 free(trans->setup_packet); 102 } 103 if (trans->buffer != NULL) { 104 free(trans->buffer); 105 } 106 107 free(trans); 108 } 109 110 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 111 { 112 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 113 if (trans == NULL) { 114 return NULL; 115 } 116 117 trans->caller = caller; 118 trans->data_caller = 0; 119 trans->buffer = NULL; 120 trans->setup_packet = NULL; 121 trans->size = 0; 122 123 return trans; 124 } 125 126 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface, 127 ipc_callid_t callid, ipc_call_t *call) 128 { 129 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 130 131 if (!usb_iface->reserve_default_address) { 132 async_answer_0(callid, ENOTSUP); 133 return; 134 } 135 136 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 137 138 int rc = usb_iface->reserve_default_address(fun, speed); 139 140 async_answer_0(callid, rc); 141 } 142 143 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface, 144 ipc_callid_t callid, ipc_call_t *call) 145 { 146 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 147 148 if (!usb_iface->release_default_address) { 149 async_answer_0(callid, ENOTSUP); 150 return; 151 } 152 153 int rc = usb_iface->release_default_address(fun); 154 155 async_answer_0(callid, rc); 156 } 157 158 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 159 ipc_callid_t callid, ipc_call_t *call) 160 { 161 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 162 163 if (!usb_iface->request_address) { 164 async_answer_0(callid, ENOTSUP); 165 return; 166 } 167 168 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 111 169 112 170 usb_address_t address; 113 int rc = usb_iface-> tell_address(device, handle, &address);114 if (rc != EOK) { 115 ipc_answer_0(callid, rc);171 int rc = usb_iface->request_address(fun, speed, &address); 172 if (rc != EOK) { 173 async_answer_0(callid, rc); 116 174 } else { 117 ipc_answer_1(callid, EOK, address); 118 } 119 } 120 121 void remote_usbhc_get_buffer(device_t *device, void *iface, 122 ipc_callid_t callid, ipc_call_t *call) 123 { 124 sysarg_t buffer_hash = DEV_IPC_GET_ARG1(*call); 125 async_transaction_t * trans = (async_transaction_t *)buffer_hash; 126 if (trans == NULL) { 127 ipc_answer_0(callid, ENOENT); 128 return; 129 } 130 if (trans->buffer == NULL) { 131 ipc_answer_0(callid, EINVAL); 132 free(trans); 133 return; 134 } 135 136 ipc_callid_t cid; 137 size_t accepted_size; 138 if (!async_data_read_receive(&cid, &accepted_size)) { 139 ipc_answer_0(callid, EINVAL); 140 return; 141 } 142 143 if (accepted_size > trans->size) { 144 accepted_size = trans->size; 145 } 146 async_data_read_finalize(cid, trans->buffer, accepted_size); 147 148 ipc_answer_1(callid, EOK, accepted_size); 149 150 free(trans->buffer); 151 free(trans); 152 } 153 154 void remote_usbhc_reserve_default_address(device_t *device, void *iface, 155 ipc_callid_t callid, ipc_call_t *call) 156 { 157 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 158 159 if (!usb_iface->reserve_default_address) { 160 ipc_answer_0(callid, ENOTSUP); 161 return; 162 } 163 164 int rc = usb_iface->reserve_default_address(device); 165 166 ipc_answer_0(callid, rc); 167 } 168 169 void remote_usbhc_release_default_address(device_t *device, void *iface, 170 ipc_callid_t callid, ipc_call_t *call) 171 { 172 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 173 174 if (!usb_iface->release_default_address) { 175 ipc_answer_0(callid, ENOTSUP); 176 return; 177 } 178 179 int rc = usb_iface->release_default_address(device); 180 181 ipc_answer_0(callid, rc); 182 } 183 184 void remote_usbhc_request_address(device_t *device, void *iface, 185 ipc_callid_t callid, ipc_call_t *call) 186 { 187 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 188 189 if (!usb_iface->request_address) { 190 ipc_answer_0(callid, ENOTSUP); 191 return; 192 } 193 194 usb_address_t address; 195 int rc = usb_iface->request_address(device, &address); 196 if (rc != EOK) { 197 ipc_answer_0(callid, rc); 198 } else { 199 ipc_answer_1(callid, EOK, (sysarg_t) address); 200 } 201 } 202 203 void remote_usbhc_bind_address(device_t *device, void *iface, 175 async_answer_1(callid, EOK, (sysarg_t) address); 176 } 177 } 178 179 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 204 180 ipc_callid_t callid, ipc_call_t *call) 205 181 { … … 207 183 208 184 if (!usb_iface->bind_address) { 209 ipc_answer_0(callid, ENOTSUP);185 async_answer_0(callid, ENOTSUP); 210 186 return; 211 187 } … … 214 190 devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 215 191 216 int rc = usb_iface->bind_address( device, address, handle);217 218 ipc_answer_0(callid, rc);219 } 220 221 void remote_usbhc_release_address(d evice_t *device, void *iface,192 int rc = usb_iface->bind_address(fun, address, handle); 193 194 async_answer_0(callid, rc); 195 } 196 197 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 222 198 ipc_callid_t callid, ipc_call_t *call) 223 199 { … … 225 201 226 202 if (!usb_iface->release_address) { 227 ipc_answer_0(callid, ENOTSUP);203 async_answer_0(callid, ENOTSUP); 228 204 return; 229 205 } … … 231 207 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 232 208 233 int rc = usb_iface->release_address( device, address);234 235 ipc_answer_0(callid, rc);236 } 237 238 239 static void callback_out(d evice_t *device,240 usb_transaction_outcome_t outcome, void *arg)209 int rc = usb_iface->release_address(fun, address); 210 211 async_answer_0(callid, rc); 212 } 213 214 215 static void callback_out(ddf_fun_t *fun, 216 int outcome, void *arg) 241 217 { 242 218 async_transaction_t *trans = (async_transaction_t *)arg; 243 219 244 // FIXME - answer according to outcome 245 ipc_answer_0(trans->caller, EOK); 246 247 free(trans); 248 } 249 250 static void callback_in(device_t *device, 251 usb_transaction_outcome_t outcome, size_t actual_size, void *arg) 220 async_answer_0(trans->caller, outcome); 221 222 async_transaction_destroy(trans); 223 } 224 225 static void callback_in(ddf_fun_t *fun, 226 int outcome, size_t actual_size, void *arg) 252 227 { 253 228 async_transaction_t *trans = (async_transaction_t *)arg; 254 229 255 // FIXME - answer according to outcome 256 ipc_answer_1(trans->caller, EOK, (sysarg_t)trans); 230 if (outcome != EOK) { 231 async_answer_0(trans->caller, outcome); 232 if (trans->data_caller) { 233 async_answer_0(trans->data_caller, EINTR); 234 } 235 async_transaction_destroy(trans); 236 return; 237 } 257 238 258 239 trans->size = actual_size; 240 241 if (trans->data_caller) { 242 async_data_read_finalize(trans->data_caller, 243 trans->buffer, actual_size); 244 } 245 246 async_answer_0(trans->caller, EOK); 247 248 async_transaction_destroy(trans); 259 249 } 260 250 … … 266 256 * @param transfer_func Transfer function (might be NULL). 267 257 */ 268 static void remote_usbhc_out_transfer(d evice_t *device,258 static void remote_usbhc_out_transfer(ddf_fun_t *fun, 269 259 ipc_callid_t callid, ipc_call_t *call, 270 260 usbhc_iface_transfer_out_t transfer_func) 271 261 { 272 262 if (!transfer_func) { 273 ipc_answer_0(callid, ENOTSUP);274 return; 275 } 276 277 size_t expected_len= DEV_IPC_GET_ARG3(*call);263 async_answer_0(callid, ENOTSUP); 264 return; 265 } 266 267 size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 278 268 usb_target_t target = { 279 269 .address = DEV_IPC_GET_ARG1(*call), … … 283 273 size_t len = 0; 284 274 void *buffer = NULL; 285 if (expected_len > 0) { 286 int rc = async_data_write_accept(&buffer, false, 287 1, USB_MAX_PAYLOAD_SIZE, 288 0, &len); 289 290 if (rc != EOK) { 291 ipc_answer_0(callid, rc); 292 return; 293 } 294 } 295 296 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 297 trans->caller = callid; 298 trans->buffer = buffer; 299 trans->size = len; 300 301 int rc = transfer_func(device, target, buffer, len, 302 callback_out, trans); 303 304 if (rc != EOK) { 305 ipc_answer_0(callid, rc); 275 276 int rc = async_data_write_accept(&buffer, false, 277 1, USB_MAX_PAYLOAD_SIZE, 278 0, &len); 279 280 if (rc != EOK) { 281 async_answer_0(callid, rc); 282 return; 283 } 284 285 async_transaction_t *trans = async_transaction_create(callid); 286 if (trans == NULL) { 306 287 if (buffer != NULL) { 307 288 free(buffer); 308 289 } 309 free(trans); 290 async_answer_0(callid, ENOMEM); 291 return; 292 } 293 294 trans->buffer = buffer; 295 trans->size = len; 296 297 rc = transfer_func(fun, target, max_packet_size, 298 buffer, len, 299 callback_out, trans); 300 301 if (rc != EOK) { 302 async_answer_0(callid, rc); 303 async_transaction_destroy(trans); 310 304 } 311 305 } … … 318 312 * @param transfer_func Transfer function (might be NULL). 319 313 */ 320 static void remote_usbhc_in_transfer(d evice_t *device,314 static void remote_usbhc_in_transfer(ddf_fun_t *fun, 321 315 ipc_callid_t callid, ipc_call_t *call, 322 316 usbhc_iface_transfer_in_t transfer_func) 323 317 { 324 318 if (!transfer_func) { 325 ipc_answer_0(callid, ENOTSUP);326 return; 327 } 328 329 size_t len= DEV_IPC_GET_ARG3(*call);319 async_answer_0(callid, ENOTSUP); 320 return; 321 } 322 323 size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 330 324 usb_target_t target = { 331 325 .address = DEV_IPC_GET_ARG1(*call), … … 333 327 }; 334 328 335 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 336 trans->caller = callid; 329 size_t len; 330 ipc_callid_t data_callid; 331 if (!async_data_read_receive(&data_callid, &len)) { 332 async_answer_0(callid, EPARTY); 333 return; 334 } 335 336 async_transaction_t *trans = async_transaction_create(callid); 337 if (trans == NULL) { 338 async_answer_0(callid, ENOMEM); 339 return; 340 } 341 trans->data_caller = data_callid; 337 342 trans->buffer = malloc(len); 338 343 trans->size = len; 339 344 340 int rc = transfer_func(device, target, trans->buffer, len, 345 int rc = transfer_func(fun, target, max_packet_size, 346 trans->buffer, len, 341 347 callback_in, trans); 342 348 343 349 if (rc != EOK) { 344 ipc_answer_0(callid, rc); 345 free(trans->buffer); 346 free(trans); 347 } 348 } 349 350 /** Process status part of control transfer. 351 * 352 * @param device Target device. 353 * @param callid Initiating caller. 354 * @param call Initiating call. 355 * @param direction Transfer direction (read ~ in, write ~ out). 356 * @param transfer_in_func Transfer function for control read (might be NULL). 357 * @param transfer_out_func Transfer function for control write (might be NULL). 358 */ 359 static void remote_usbhc_status_transfer(device_t *device, 360 ipc_callid_t callid, ipc_call_t *call, 361 usb_direction_t direction, 362 int (*transfer_in_func)(device_t *, usb_target_t, 363 usbhc_iface_transfer_in_callback_t, void *), 364 int (*transfer_out_func)(device_t *, usb_target_t, 365 usbhc_iface_transfer_out_callback_t, void *)) 366 { 367 switch (direction) { 368 case USB_DIRECTION_IN: 369 if (!transfer_in_func) { 370 ipc_answer_0(callid, ENOTSUP); 371 return; 372 } 373 break; 374 case USB_DIRECTION_OUT: 375 if (!transfer_out_func) { 376 ipc_answer_0(callid, ENOTSUP); 377 return; 378 } 379 break; 380 default: 381 assert(false && "unreachable code"); 382 break; 350 async_answer_0(callid, rc); 351 async_transaction_destroy(trans); 352 } 353 } 354 355 void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface, 356 ipc_callid_t callid, ipc_call_t *call) 357 { 358 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 359 assert(usb_iface != NULL); 360 361 return remote_usbhc_out_transfer(fun, callid, call, 362 usb_iface->interrupt_out); 363 } 364 365 void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface, 366 ipc_callid_t callid, ipc_call_t *call) 367 { 368 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 369 assert(usb_iface != NULL); 370 371 return remote_usbhc_in_transfer(fun, callid, call, 372 usb_iface->interrupt_in); 373 } 374 375 void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface, 376 ipc_callid_t callid, ipc_call_t *call) 377 { 378 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 379 assert(usb_iface != NULL); 380 381 return remote_usbhc_out_transfer(fun, callid, call, 382 usb_iface->bulk_out); 383 } 384 385 void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface, 386 ipc_callid_t callid, ipc_call_t *call) 387 { 388 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 389 assert(usb_iface != NULL); 390 391 return remote_usbhc_in_transfer(fun, callid, call, 392 usb_iface->bulk_in); 393 } 394 395 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface, 396 ipc_callid_t callid, ipc_call_t *call) 397 { 398 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 399 assert(usb_iface != NULL); 400 401 if (!usb_iface->control_write) { 402 async_answer_0(callid, ENOTSUP); 403 return; 383 404 } 384 405 … … 387 408 .endpoint = DEV_IPC_GET_ARG2(*call) 388 409 }; 389 390 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 391 trans->caller = callid; 392 trans->buffer = NULL; 393 trans->size = 0; 410 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call); 411 size_t max_packet_size = DEV_IPC_GET_ARG4(*call); 394 412 395 413 int rc; 396 switch (direction) { 397 case USB_DIRECTION_IN: 398 rc = transfer_in_func(device, target, 399 callback_in, trans); 400 break; 401 case USB_DIRECTION_OUT: 402 rc = transfer_out_func(device, target, 403 callback_out, trans); 404 break; 405 default: 406 assert(false && "unreachable code"); 407 break; 408 } 409 410 if (rc != EOK) { 411 ipc_answer_0(callid, rc); 412 free(trans); 413 } 414 return; 415 } 416 417 418 void remote_usbhc_interrupt_out(device_t *device, void *iface, 419 ipc_callid_t callid, ipc_call_t *call) 414 415 void *setup_packet = NULL; 416 void *data_buffer = NULL; 417 size_t setup_packet_len = 0; 418 419 rc = async_data_write_accept(&setup_packet, false, 420 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len); 421 if (rc != EOK) { 422 async_answer_0(callid, rc); 423 return; 424 } 425 426 if (data_buffer_len > 0) { 427 rc = async_data_write_accept(&data_buffer, false, 428 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len); 429 if (rc != EOK) { 430 async_answer_0(callid, rc); 431 free(setup_packet); 432 return; 433 } 434 } 435 436 async_transaction_t *trans = async_transaction_create(callid); 437 if (trans == NULL) { 438 async_answer_0(callid, ENOMEM); 439 free(setup_packet); 440 free(data_buffer); 441 return; 442 } 443 trans->setup_packet = setup_packet; 444 trans->buffer = data_buffer; 445 trans->size = data_buffer_len; 446 447 rc = usb_iface->control_write(fun, target, max_packet_size, 448 setup_packet, setup_packet_len, 449 data_buffer, data_buffer_len, 450 callback_out, trans); 451 452 if (rc != EOK) { 453 async_answer_0(callid, rc); 454 async_transaction_destroy(trans); 455 } 456 } 457 458 459 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface, 460 ipc_callid_t callid, ipc_call_t *call) 420 461 { 421 462 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 422 463 assert(usb_iface != NULL); 423 464 424 return remote_usbhc_out_transfer(device, callid, call, 425 usb_iface->interrupt_out); 426 } 427 428 void remote_usbhc_interrupt_in(device_t *device, void *iface, 429 ipc_callid_t callid, ipc_call_t *call) 430 { 431 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 432 assert(usb_iface != NULL); 433 434 return remote_usbhc_in_transfer(device, callid, call, 435 usb_iface->interrupt_in); 436 } 437 438 void remote_usbhc_control_write_setup(device_t *device, void *iface, 439 ipc_callid_t callid, ipc_call_t *call) 440 { 441 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 442 assert(usb_iface != NULL); 443 444 return remote_usbhc_out_transfer(device, callid, call, 445 usb_iface->control_write_setup); 446 } 447 448 void remote_usbhc_control_write_data(device_t *device, void *iface, 449 ipc_callid_t callid, ipc_call_t *call) 450 { 451 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 452 assert(usb_iface != NULL); 453 454 return remote_usbhc_out_transfer(device, callid, call, 455 usb_iface->control_write_data); 456 } 457 458 void remote_usbhc_control_write_status(device_t *device, void *iface, 459 ipc_callid_t callid, ipc_call_t *call) 460 { 461 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 462 assert(usb_iface != NULL); 463 464 return remote_usbhc_status_transfer(device, callid, call, 465 USB_DIRECTION_IN, usb_iface->control_write_status, NULL); 466 } 467 468 void remote_usbhc_control_read_setup(device_t *device, void *iface, 469 ipc_callid_t callid, ipc_call_t *call) 470 { 471 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 472 assert(usb_iface != NULL); 473 474 return remote_usbhc_out_transfer(device, callid, call, 475 usb_iface->control_read_setup); 476 } 477 478 void remote_usbhc_control_read_data(device_t *device, void *iface, 479 ipc_callid_t callid, ipc_call_t *call) 480 { 481 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 482 assert(usb_iface != NULL); 483 484 return remote_usbhc_in_transfer(device, callid, call, 485 usb_iface->control_read_data); 486 } 487 488 void remote_usbhc_control_read_status(device_t *device, void *iface, 489 ipc_callid_t callid, ipc_call_t *call) 490 { 491 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 492 assert(usb_iface != NULL); 493 494 return remote_usbhc_status_transfer(device, callid, call, 495 USB_DIRECTION_OUT, NULL, usb_iface->control_read_status); 465 if (!usb_iface->control_read) { 466 async_answer_0(callid, ENOTSUP); 467 return; 468 } 469 470 usb_target_t target = { 471 .address = DEV_IPC_GET_ARG1(*call), 472 .endpoint = DEV_IPC_GET_ARG2(*call) 473 }; 474 size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 475 476 int rc; 477 478 void *setup_packet = NULL; 479 size_t setup_packet_len = 0; 480 size_t data_len = 0; 481 482 rc = async_data_write_accept(&setup_packet, false, 483 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len); 484 if (rc != EOK) { 485 async_answer_0(callid, rc); 486 return; 487 } 488 489 ipc_callid_t data_callid; 490 if (!async_data_read_receive(&data_callid, &data_len)) { 491 async_answer_0(callid, EPARTY); 492 free(setup_packet); 493 return; 494 } 495 496 async_transaction_t *trans = async_transaction_create(callid); 497 if (trans == NULL) { 498 async_answer_0(callid, ENOMEM); 499 free(setup_packet); 500 return; 501 } 502 trans->data_caller = data_callid; 503 trans->setup_packet = setup_packet; 504 trans->size = data_len; 505 trans->buffer = malloc(data_len); 506 if (trans->buffer == NULL) { 507 async_answer_0(callid, ENOMEM); 508 async_transaction_destroy(trans); 509 return; 510 } 511 512 rc = usb_iface->control_read(fun, target, max_packet_size, 513 setup_packet, setup_packet_len, 514 trans->buffer, trans->size, 515 callback_in, trans); 516 517 if (rc != EOK) { 518 async_answer_0(callid, rc); 519 async_transaction_destroy(trans); 520 } 496 521 } 497 522
Note:
See TracChangeset
for help on using the changeset viewer.
