Changes in uspace/lib/drv/generic/remote_usbhc.c [357a302:6edd494] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/remote_usbhc.c
r357a302 r6edd494 1 1 /* 2 * Copyright (c) 2010 -2011Vojtech Horky2 * Copyright (c) 2010 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 33 33 */ 34 34 35 #include <ipc/ipc.h> 35 36 #include <async.h> 36 37 #include <errno.h> … … 40 41 41 42 #define USB_MAX_PAYLOAD_SIZE 1020 42 #define HACK_MAX_PACKET_SIZE 8 43 #define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4 44 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 *); 45 46 static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *); 46 47 static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *); 47 static void remote_usbhc_bulk_out(device_t *, void *, ipc_callid_t, ipc_call_t *); 48 static void remote_usbhc_bulk_in(device_t *, void *, ipc_callid_t, ipc_call_t *); 49 static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_control_read(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 *); 51 54 static void remote_usbhc_reserve_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *); 52 55 static void remote_usbhc_release_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *); … … 58 61 /** Remote USB host controller interface operations. */ 59 62 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 63 remote_usbhc_get_address, 64 65 remote_usbhc_get_buffer, 66 60 67 remote_usbhc_reserve_default_address, 61 68 remote_usbhc_release_default_address, … … 68 75 remote_usbhc_interrupt_in, 69 76 70 remote_usbhc_bulk_out, 71 remote_usbhc_bulk_in, 72 73 remote_usbhc_control_write, 74 remote_usbhc_control_read 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 75 84 }; 76 85 … … 85 94 typedef struct { 86 95 ipc_callid_t caller; 87 ipc_callid_t data_caller;88 96 void *buffer; 89 void *setup_packet;90 97 size_t size; 91 98 } async_transaction_t; 92 99 93 static void async_transaction_destroy(async_transaction_t *trans) 94 { 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); 111 112 usb_address_t address; 113 int rc = usb_iface->tell_address(device, handle, &address); 114 if (rc != EOK) { 115 ipc_answer_0(callid, rc); 116 } 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; 95 126 if (trans == NULL) { 96 return; 97 } 98 99 if (trans->setup_packet != NULL) { 100 free(trans->setup_packet); 101 } 102 if (trans->buffer != NULL) { 103 free(trans->buffer); 104 } 105 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); 106 151 free(trans); 107 152 } 108 153 109 static async_transaction_t *async_transaction_create(ipc_callid_t caller)110 {111 async_transaction_t *trans = malloc(sizeof(async_transaction_t));112 if (trans == NULL) {113 return NULL;114 }115 116 trans->caller = caller;117 trans->data_caller = 0;118 trans->buffer = NULL;119 trans->setup_packet = NULL;120 trans->size = 0;121 122 return trans;123 }124 125 154 void remote_usbhc_reserve_default_address(device_t *device, void *iface, 126 155 ipc_callid_t callid, ipc_call_t *call) … … 129 158 130 159 if (!usb_iface->reserve_default_address) { 131 async_answer_0(callid, ENOTSUP); 132 return; 133 } 134 135 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 136 137 int rc = usb_iface->reserve_default_address(device, speed); 138 139 async_answer_0(callid, rc); 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); 140 167 } 141 168 … … 146 173 147 174 if (!usb_iface->release_default_address) { 148 async_answer_0(callid, ENOTSUP);175 ipc_answer_0(callid, ENOTSUP); 149 176 return; 150 177 } … … 152 179 int rc = usb_iface->release_default_address(device); 153 180 154 async_answer_0(callid, rc);181 ipc_answer_0(callid, rc); 155 182 } 156 183 … … 161 188 162 189 if (!usb_iface->request_address) { 163 async_answer_0(callid, ENOTSUP); 164 return; 165 } 166 167 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 190 ipc_answer_0(callid, ENOTSUP); 191 return; 192 } 168 193 169 194 usb_address_t address; 170 int rc = usb_iface->request_address(device, speed,&address);195 int rc = usb_iface->request_address(device, &address); 171 196 if (rc != EOK) { 172 async_answer_0(callid, rc);197 ipc_answer_0(callid, rc); 173 198 } else { 174 async_answer_1(callid, EOK, (sysarg_t) address);199 ipc_answer_1(callid, EOK, (sysarg_t) address); 175 200 } 176 201 } … … 182 207 183 208 if (!usb_iface->bind_address) { 184 async_answer_0(callid, ENOTSUP);209 ipc_answer_0(callid, ENOTSUP); 185 210 return; 186 211 } … … 191 216 int rc = usb_iface->bind_address(device, address, handle); 192 217 193 async_answer_0(callid, rc);218 ipc_answer_0(callid, rc); 194 219 } 195 220 … … 200 225 201 226 if (!usb_iface->release_address) { 202 async_answer_0(callid, ENOTSUP);227 ipc_answer_0(callid, ENOTSUP); 203 228 return; 204 229 } … … 208 233 int rc = usb_iface->release_address(device, address); 209 234 210 async_answer_0(callid, rc);235 ipc_answer_0(callid, rc); 211 236 } 212 237 213 238 214 239 static void callback_out(device_t *device, 215 int outcome, void *arg)240 usb_transaction_outcome_t outcome, void *arg) 216 241 { 217 242 async_transaction_t *trans = (async_transaction_t *)arg; 218 243 219 async_answer_0(trans->caller, outcome); 220 221 async_transaction_destroy(trans); 244 // FIXME - answer according to outcome 245 ipc_answer_0(trans->caller, EOK); 246 247 free(trans); 222 248 } 223 249 224 250 static void callback_in(device_t *device, 225 int outcome, size_t actual_size, void *arg)251 usb_transaction_outcome_t outcome, size_t actual_size, void *arg) 226 252 { 227 253 async_transaction_t *trans = (async_transaction_t *)arg; 228 254 229 if (outcome != EOK) { 230 async_answer_0(trans->caller, outcome); 231 if (trans->data_caller) { 232 async_answer_0(trans->data_caller, EINTR); 233 } 234 async_transaction_destroy(trans); 235 return; 236 } 255 // FIXME - answer according to outcome 256 ipc_answer_1(trans->caller, EOK, (sysarg_t)trans); 237 257 238 258 trans->size = actual_size; 239 240 if (trans->data_caller) {241 async_data_read_finalize(trans->data_caller,242 trans->buffer, actual_size);243 }244 245 async_answer_0(trans->caller, EOK);246 247 async_transaction_destroy(trans);248 259 } 249 260 … … 260 271 { 261 272 if (!transfer_func) { 262 async_answer_0(callid, ENOTSUP);263 return; 264 } 265 266 size_t max_packet_size= DEV_IPC_GET_ARG3(*call);273 ipc_answer_0(callid, ENOTSUP); 274 return; 275 } 276 277 size_t expected_len = DEV_IPC_GET_ARG3(*call); 267 278 usb_target_t target = { 268 279 .address = DEV_IPC_GET_ARG1(*call), … … 272 283 size_t len = 0; 273 284 void *buffer = NULL; 274 275 int rc = async_data_write_accept(&buffer, false, 276 1, USB_MAX_PAYLOAD_SIZE, 277 0, &len); 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); 278 303 279 304 if (rc != EOK) { 280 async_answer_0(callid, rc); 281 return; 282 } 283 284 async_transaction_t *trans = async_transaction_create(callid); 285 if (trans == NULL) { 305 ipc_answer_0(callid, rc); 286 306 if (buffer != NULL) { 287 307 free(buffer); 288 308 } 289 async_answer_0(callid, ENOMEM); 290 return; 291 } 292 293 trans->buffer = buffer; 294 trans->size = len; 295 296 rc = transfer_func(device, target, max_packet_size, 297 buffer, len, 298 callback_out, trans); 299 300 if (rc != EOK) { 301 async_answer_0(callid, rc); 302 async_transaction_destroy(trans); 309 free(trans); 303 310 } 304 311 } … … 316 323 { 317 324 if (!transfer_func) { 318 async_answer_0(callid, ENOTSUP);319 return; 320 } 321 322 size_t max_packet_size= DEV_IPC_GET_ARG3(*call);325 ipc_answer_0(callid, ENOTSUP); 326 return; 327 } 328 329 size_t len = DEV_IPC_GET_ARG3(*call); 323 330 usb_target_t target = { 324 331 .address = DEV_IPC_GET_ARG1(*call), … … 326 333 }; 327 334 328 size_t len; 329 ipc_callid_t data_callid; 330 if (!async_data_read_receive(&data_callid, &len)) { 331 async_answer_0(callid, EPARTY); 332 return; 333 } 334 335 async_transaction_t *trans = async_transaction_create(callid); 336 if (trans == NULL) { 337 async_answer_0(callid, ENOMEM); 338 return; 339 } 340 trans->data_caller = data_callid; 335 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 336 trans->caller = callid; 341 337 trans->buffer = malloc(len); 342 338 trans->size = len; 343 339 344 int rc = transfer_func(device, target, max_packet_size, 345 trans->buffer, len, 340 int rc = transfer_func(device, target, trans->buffer, len, 346 341 callback_in, trans); 347 342 348 343 if (rc != EOK) { 349 async_answer_0(callid, rc); 350 async_transaction_destroy(trans); 351 } 352 } 353 354 void remote_usbhc_interrupt_out(device_t *device, void *iface, 355 ipc_callid_t callid, ipc_call_t *call) 356 { 357 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 358 assert(usb_iface != NULL); 359 360 return remote_usbhc_out_transfer(device, callid, call, 361 usb_iface->interrupt_out); 362 } 363 364 void remote_usbhc_interrupt_in(device_t *device, void *iface, 365 ipc_callid_t callid, ipc_call_t *call) 366 { 367 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 368 assert(usb_iface != NULL); 369 370 return remote_usbhc_in_transfer(device, callid, call, 371 usb_iface->interrupt_in); 372 } 373 374 void remote_usbhc_bulk_out(device_t *device, void *iface, 375 ipc_callid_t callid, ipc_call_t *call) 376 { 377 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 378 assert(usb_iface != NULL); 379 380 return remote_usbhc_out_transfer(device, callid, call, 381 usb_iface->bulk_out); 382 } 383 384 void remote_usbhc_bulk_in(device_t *device, void *iface, 385 ipc_callid_t callid, ipc_call_t *call) 386 { 387 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 388 assert(usb_iface != NULL); 389 390 return remote_usbhc_in_transfer(device, callid, call, 391 usb_iface->bulk_in); 392 } 393 394 void remote_usbhc_control_write(device_t *device, void *iface, 395 ipc_callid_t callid, ipc_call_t *call) 396 { 397 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 398 assert(usb_iface != NULL); 399 400 if (!usb_iface->control_write) { 401 async_answer_0(callid, ENOTSUP); 402 return; 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; 403 383 } 404 384 … … 407 387 .endpoint = DEV_IPC_GET_ARG2(*call) 408 388 }; 409 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call); 410 size_t max_packet_size = DEV_IPC_GET_ARG4(*call); 389 390 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 391 trans->caller = callid; 392 trans->buffer = NULL; 393 trans->size = 0; 411 394 412 395 int rc; 413 414 void *setup_packet = NULL; 415 void *data_buffer = NULL; 416 size_t setup_packet_len = 0; 417 418 rc = async_data_write_accept(&setup_packet, false, 419 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len); 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 420 410 if (rc != EOK) { 421 async_answer_0(callid, rc); 422 return; 423 } 424 425 if (data_buffer_len > 0) { 426 rc = async_data_write_accept(&data_buffer, false, 427 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len); 428 if (rc != EOK) { 429 async_answer_0(callid, rc); 430 free(setup_packet); 431 return; 432 } 433 } 434 435 async_transaction_t *trans = async_transaction_create(callid); 436 if (trans == NULL) { 437 async_answer_0(callid, ENOMEM); 438 free(setup_packet); 439 free(data_buffer); 440 return; 441 } 442 trans->setup_packet = setup_packet; 443 trans->buffer = data_buffer; 444 trans->size = data_buffer_len; 445 446 rc = usb_iface->control_write(device, target, max_packet_size, 447 setup_packet, setup_packet_len, 448 data_buffer, data_buffer_len, 449 callback_out, trans); 450 451 if (rc != EOK) { 452 async_answer_0(callid, rc); 453 async_transaction_destroy(trans); 454 } 455 } 456 457 458 void remote_usbhc_control_read(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 if (!usb_iface->control_read) { 465 async_answer_0(callid, ENOTSUP); 466 return; 467 } 468 469 usb_target_t target = { 470 .address = DEV_IPC_GET_ARG1(*call), 471 .endpoint = DEV_IPC_GET_ARG2(*call) 472 }; 473 size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 474 475 int rc; 476 477 void *setup_packet = NULL; 478 size_t setup_packet_len = 0; 479 size_t data_len = 0; 480 481 rc = async_data_write_accept(&setup_packet, false, 482 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len); 483 if (rc != EOK) { 484 async_answer_0(callid, rc); 485 return; 486 } 487 488 ipc_callid_t data_callid; 489 if (!async_data_read_receive(&data_callid, &data_len)) { 490 async_answer_0(callid, EPARTY); 491 free(setup_packet); 492 return; 493 } 494 495 async_transaction_t *trans = async_transaction_create(callid); 496 if (trans == NULL) { 497 async_answer_0(callid, ENOMEM); 498 free(setup_packet); 499 return; 500 } 501 trans->data_caller = data_callid; 502 trans->setup_packet = setup_packet; 503 trans->size = data_len; 504 trans->buffer = malloc(data_len); 505 if (trans->buffer == NULL) { 506 async_answer_0(callid, ENOMEM); 507 async_transaction_destroy(trans); 508 return; 509 } 510 511 rc = usb_iface->control_read(device, target, max_packet_size, 512 setup_packet, setup_packet_len, 513 trans->buffer, trans->size, 514 callback_in, trans); 515 516 if (rc != EOK) { 517 async_answer_0(callid, rc); 518 async_transaction_destroy(trans); 519 } 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) 420 { 421 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 422 assert(usb_iface != NULL); 423 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); 520 496 } 521 497
Note:
See TracChangeset
for help on using the changeset viewer.