Changeset fd07e526 in mainline for uspace/lib
- Timestamp:
- 2011-09-16T14:50:20Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 432a269, d1e18573
- Parents:
- 47fecbb (diff), 82a31261 (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. - Location:
- uspace/lib
- Files:
-
- 3 added
- 1 deleted
- 13 edited
- 3 moved
-
c/generic/as.c (modified) (1 diff)
-
c/include/as.h (modified) (1 diff)
-
drv/generic/remote_usbhc.c (modified) (10 diffs)
-
drv/include/usbhc_iface.h (modified) (3 diffs)
-
usb/include/usb/hc.h (modified) (1 diff)
-
usb/include/usb/usb.h (modified) (4 diffs)
-
usbdev/src/pipesinit.c (modified) (2 diffs)
-
usbdev/src/pipesio.c (modified) (7 diffs)
-
usbhost/Makefile (modified) (1 diff)
-
usbhost/include/usb/host/batch.h (deleted)
-
usbhost/include/usb/host/endpoint.h (modified) (2 diffs)
-
usbhost/include/usb/host/hcd.h (added)
-
usbhost/include/usb/host/usb_device_manager.h (moved) (moved from uspace/lib/usbhost/include/usb/host/device_keeper.h ) (4 diffs)
-
usbhost/include/usb/host/usb_endpoint_manager.h (modified) (4 diffs)
-
usbhost/include/usb/host/usb_transfer_batch.h (added)
-
usbhost/src/endpoint.c (modified) (3 diffs)
-
usbhost/src/iface.c (added)
-
usbhost/src/usb_device_manager.c (moved) (moved from uspace/lib/usbhost/src/device_keeper.c ) (8 diffs)
-
usbhost/src/usb_endpoint_manager.c (modified) (10 diffs)
-
usbhost/src/usb_transfer_batch.c (moved) (moved from uspace/lib/usbhost/src/batch.c ) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/as.c
r47fecbb rfd07e526 123 123 * @retval ENOENT Mapping not found. 124 124 */ 125 int as_get_physical_mapping( void *address, uintptr_t *frame)125 int as_get_physical_mapping(const void *address, uintptr_t *frame) 126 126 { 127 127 uintptr_t tmp_frame; -
uspace/lib/c/include/as.h
r47fecbb rfd07e526 60 60 extern void *set_maxheapsize(size_t); 61 61 extern void *as_get_mappable_page(size_t); 62 extern int as_get_physical_mapping( void *, uintptr_t *);62 extern int as_get_physical_mapping(const void *, uintptr_t *); 63 63 64 64 #endif -
uspace/lib/drv/generic/remote_usbhc.c
r47fecbb rfd07e526 41 41 42 42 #define USB_MAX_PAYLOAD_SIZE 1020 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 *); 43 52 44 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 45 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 56 48 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 49 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 50 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 58 52 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 59 53 60 54 /** Remote USB host controller interface operations. */ 61 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 62 remote_usbhc_request_address, 63 remote_usbhc_bind_address, 64 remote_usbhc_find_by_address, 65 remote_usbhc_release_address, 66 67 remote_usbhc_interrupt_out, 68 remote_usbhc_interrupt_in, 69 70 remote_usbhc_bulk_out, 71 remote_usbhc_bulk_in, 72 73 remote_usbhc_control_write, 74 remote_usbhc_control_read, 75 76 remote_usbhc_register_endpoint, 77 remote_usbhc_unregister_endpoint 55 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 56 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address, 57 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 58 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address, 59 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 60 61 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, 62 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint, 63 64 [IPC_M_USBHC_READ] = remote_usbhc_read, 65 [IPC_M_USBHC_WRITE] = remote_usbhc_write, 78 66 }; 79 67 … … 90 78 ipc_callid_t data_caller; 91 79 void *buffer; 92 void *setup_packet;93 80 size_t size; 94 81 } async_transaction_t; … … 98 85 if (trans == NULL) { 99 86 return; 100 }101 102 if (trans->setup_packet != NULL) {103 free(trans->setup_packet);104 87 } 105 88 if (trans->buffer != NULL) { … … 120 103 trans->data_caller = 0; 121 104 trans->buffer = NULL; 122 trans->setup_packet = NULL;123 105 trans->size = 0; 124 106 … … 135 117 return; 136 118 } 137 119 138 120 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 139 121 … … 239 221 async_transaction_destroy(trans); 240 222 } 241 242 /** Process an outgoing transfer (both OUT and SETUP).243 *244 * @param device Target device.245 * @param callid Initiating caller.246 * @param call Initiating call.247 * @param transfer_func Transfer function (might be NULL).248 */249 static void remote_usbhc_out_transfer(ddf_fun_t *fun,250 ipc_callid_t callid, ipc_call_t *call,251 usbhc_iface_transfer_out_t transfer_func)252 {253 if (!transfer_func) {254 async_answer_0(callid, ENOTSUP);255 return;256 }257 258 usb_target_t target = {259 .address = DEV_IPC_GET_ARG1(*call),260 .endpoint = DEV_IPC_GET_ARG2(*call)261 };262 263 size_t len = 0;264 void *buffer = NULL;265 266 int rc = async_data_write_accept(&buffer, false,267 1, USB_MAX_PAYLOAD_SIZE,268 0, &len);269 270 if (rc != EOK) {271 async_answer_0(callid, rc);272 return;273 }274 275 async_transaction_t *trans = async_transaction_create(callid);276 if (trans == NULL) {277 if (buffer != NULL) {278 free(buffer);279 }280 async_answer_0(callid, ENOMEM);281 return;282 }283 284 trans->buffer = buffer;285 trans->size = len;286 287 rc = transfer_func(fun, target,288 buffer, len,289 callback_out, trans);290 291 if (rc != EOK) {292 async_answer_0(callid, rc);293 async_transaction_destroy(trans);294 }295 }296 297 /** Process an incoming transfer.298 *299 * @param device Target device.300 * @param callid Initiating caller.301 * @param call Initiating call.302 * @param transfer_func Transfer function (might be NULL).303 */304 static void remote_usbhc_in_transfer(ddf_fun_t *fun,305 ipc_callid_t callid, ipc_call_t *call,306 usbhc_iface_transfer_in_t transfer_func)307 {308 if (!transfer_func) {309 async_answer_0(callid, ENOTSUP);310 return;311 }312 313 usb_target_t target = {314 .address = DEV_IPC_GET_ARG1(*call),315 .endpoint = DEV_IPC_GET_ARG2(*call)316 };317 318 size_t len;319 ipc_callid_t data_callid;320 if (!async_data_read_receive(&data_callid, &len)) {321 async_answer_0(callid, EPARTY);322 return;323 }324 325 async_transaction_t *trans = async_transaction_create(callid);326 if (trans == NULL) {327 async_answer_0(data_callid, ENOMEM);328 async_answer_0(callid, ENOMEM);329 return;330 }331 trans->data_caller = data_callid;332 trans->buffer = malloc(len);333 trans->size = len;334 335 int rc = transfer_func(fun, target,336 trans->buffer, len,337 callback_in, trans);338 339 if (rc != EOK) {340 async_answer_0(data_callid, rc);341 async_answer_0(callid, rc);342 async_transaction_destroy(trans);343 }344 }345 346 void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,347 ipc_callid_t callid, ipc_call_t *call)348 {349 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;350 assert(usb_iface != NULL);351 352 return remote_usbhc_out_transfer(fun, callid, call,353 usb_iface->interrupt_out);354 }355 356 void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,357 ipc_callid_t callid, ipc_call_t *call)358 {359 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;360 assert(usb_iface != NULL);361 362 return remote_usbhc_in_transfer(fun, callid, call,363 usb_iface->interrupt_in);364 }365 366 void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,367 ipc_callid_t callid, ipc_call_t *call)368 {369 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;370 assert(usb_iface != NULL);371 372 return remote_usbhc_out_transfer(fun, callid, call,373 usb_iface->bulk_out);374 }375 376 void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,377 ipc_callid_t callid, ipc_call_t *call)378 {379 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;380 assert(usb_iface != NULL);381 382 return remote_usbhc_in_transfer(fun, callid, call,383 usb_iface->bulk_in);384 }385 386 void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,387 ipc_callid_t callid, ipc_call_t *call)388 {389 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;390 assert(usb_iface != NULL);391 392 if (!usb_iface->control_write) {393 async_answer_0(callid, ENOTSUP);394 return;395 }396 397 usb_target_t target = {398 .address = DEV_IPC_GET_ARG1(*call),399 .endpoint = DEV_IPC_GET_ARG2(*call)400 };401 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);402 403 int rc;404 405 void *setup_packet = NULL;406 void *data_buffer = NULL;407 size_t setup_packet_len = 0;408 409 rc = async_data_write_accept(&setup_packet, false,410 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);411 if (rc != EOK) {412 async_answer_0(callid, rc);413 return;414 }415 416 if (data_buffer_len > 0) {417 rc = async_data_write_accept(&data_buffer, false,418 1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);419 if (rc != EOK) {420 async_answer_0(callid, rc);421 free(setup_packet);422 return;423 }424 }425 426 async_transaction_t *trans = async_transaction_create(callid);427 if (trans == NULL) {428 async_answer_0(callid, ENOMEM);429 free(setup_packet);430 free(data_buffer);431 return;432 }433 trans->setup_packet = setup_packet;434 trans->buffer = data_buffer;435 trans->size = data_buffer_len;436 437 rc = usb_iface->control_write(fun, target,438 setup_packet, setup_packet_len,439 data_buffer, data_buffer_len,440 callback_out, trans);441 442 if (rc != EOK) {443 async_answer_0(callid, rc);444 async_transaction_destroy(trans);445 }446 }447 448 449 void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,450 ipc_callid_t callid, ipc_call_t *call)451 {452 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;453 assert(usb_iface != NULL);454 455 if (!usb_iface->control_read) {456 async_answer_0(callid, ENOTSUP);457 return;458 }459 460 usb_target_t target = {461 .address = DEV_IPC_GET_ARG1(*call),462 .endpoint = DEV_IPC_GET_ARG2(*call)463 };464 465 int rc;466 467 void *setup_packet = NULL;468 size_t setup_packet_len = 0;469 size_t data_len = 0;470 471 rc = async_data_write_accept(&setup_packet, false,472 1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);473 if (rc != EOK) {474 async_answer_0(callid, rc);475 return;476 }477 478 ipc_callid_t data_callid;479 if (!async_data_read_receive(&data_callid, &data_len)) {480 async_answer_0(callid, EPARTY);481 free(setup_packet);482 return;483 }484 485 async_transaction_t *trans = async_transaction_create(callid);486 if (trans == NULL) {487 async_answer_0(data_callid, ENOMEM);488 async_answer_0(callid, ENOMEM);489 free(setup_packet);490 return;491 }492 trans->data_caller = data_callid;493 trans->setup_packet = setup_packet;494 trans->size = data_len;495 trans->buffer = malloc(data_len);496 if (trans->buffer == NULL) {497 async_answer_0(data_callid, ENOMEM);498 async_answer_0(callid, ENOMEM);499 async_transaction_destroy(trans);500 return;501 }502 503 rc = usb_iface->control_read(fun, target,504 setup_packet, setup_packet_len,505 trans->buffer, trans->size,506 callback_in, trans);507 508 if (rc != EOK) {509 async_answer_0(data_callid, rc);510 async_answer_0(callid, rc);511 async_transaction_destroy(trans);512 }513 }514 515 223 516 224 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, … … 535 243 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 536 244 537 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 538 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 245 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 539 246 540 247 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); … … 551 258 #undef _INIT_FROM_LOW_DATA3 552 259 553 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,554 t ransfer_type, direction, max_packet_size, interval);260 int rc = usb_iface->register_endpoint(fun, target.address, speed, 261 target.endpoint, transfer_type, direction, max_packet_size, interval); 555 262 556 263 async_answer_0(callid, rc); 557 264 } 558 559 265 560 266 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface, … … 578 284 } 579 285 286 void remote_usbhc_read( 287 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 288 { 289 assert(fun); 290 assert(iface); 291 assert(call); 292 293 const usbhc_iface_t *hc_iface = iface; 294 295 if (!hc_iface->read) { 296 async_answer_0(callid, ENOTSUP); 297 return; 298 } 299 300 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 301 const uint64_t setup = 302 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 303 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 304 305 async_transaction_t *trans = async_transaction_create(callid); 306 if (trans == NULL) { 307 async_answer_0(callid, ENOMEM); 308 return; 309 } 310 311 if (!async_data_read_receive(&trans->data_caller, &trans->size)) { 312 async_answer_0(callid, EPARTY); 313 return; 314 } 315 316 trans->buffer = malloc(trans->size); 317 if (trans->buffer == NULL) { 318 async_answer_0(trans->data_caller, ENOMEM); 319 async_answer_0(callid, ENOMEM); 320 async_transaction_destroy(trans); 321 } 322 323 const int rc = hc_iface->read( 324 fun, target, setup, trans->buffer, trans->size, callback_in, trans); 325 326 if (rc != EOK) { 327 async_answer_0(trans->data_caller, rc); 328 async_answer_0(callid, rc); 329 async_transaction_destroy(trans); 330 } 331 } 332 333 void remote_usbhc_write( 334 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 335 { 336 assert(fun); 337 assert(iface); 338 assert(call); 339 340 const usbhc_iface_t *hc_iface = iface; 341 342 if (!hc_iface->write) { 343 async_answer_0(callid, ENOTSUP); 344 return; 345 } 346 347 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) }; 348 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 349 const uint64_t setup = 350 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 351 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 352 353 async_transaction_t *trans = async_transaction_create(callid); 354 if (trans == NULL) { 355 async_answer_0(callid, ENOMEM); 356 return; 357 } 358 359 if (data_buffer_len > 0) { 360 int rc = async_data_write_accept(&trans->buffer, false, 361 1, USB_MAX_PAYLOAD_SIZE, 362 0, &trans->size); 363 364 if (rc != EOK) { 365 async_answer_0(callid, rc); 366 async_transaction_destroy(trans); 367 return; 368 } 369 } 370 371 int rc = hc_iface->write( 372 fun, target, setup, trans->buffer, trans->size, callback_out, trans); 373 374 if (rc != EOK) { 375 async_answer_0(callid, rc); 376 async_transaction_destroy(trans); 377 } 378 } 379 580 380 581 381 /** -
uspace/lib/drv/include/usbhc_iface.h
r47fecbb rfd07e526 123 123 IPC_M_USBHC_RELEASE_ADDRESS, 124 124 125 126 /** Send interrupt data to device.127 * See explanation at usb_iface_funcs_t (OUT transaction).128 */129 IPC_M_USBHC_INTERRUPT_OUT,130 131 /** Get interrupt data from device.132 * See explanation at usb_iface_funcs_t (IN transaction).133 */134 IPC_M_USBHC_INTERRUPT_IN,135 136 /** Send bulk data to device.137 * See explanation at usb_iface_funcs_t (OUT transaction).138 */139 IPC_M_USBHC_BULK_OUT,140 141 /** Get bulk data from device.142 * See explanation at usb_iface_funcs_t (IN transaction).143 */144 IPC_M_USBHC_BULK_IN,145 146 /** Issue control WRITE transfer.147 * See explanation at usb_iface_funcs_t (OUT transaction) for148 * call parameters.149 * This call is immediately followed by two IPC data writes150 * from the caller (setup packet and actual data).151 */152 IPC_M_USBHC_CONTROL_WRITE,153 154 /** Issue control READ transfer.155 * See explanation at usb_iface_funcs_t (IN transaction) for156 * call parameters.157 * This call is immediately followed by IPC data write from the caller158 * (setup packet) and IPC data read (buffer that was read).159 */160 IPC_M_USBHC_CONTROL_READ,161 162 125 /** Register endpoint attributes at host controller. 163 126 * This is used to reserve portion of USB bandwidth. … … 185 148 * - ENOENT - unknown endpoint 186 149 */ 187 IPC_M_USBHC_UNREGISTER_ENDPOINT 150 IPC_M_USBHC_UNREGISTER_ENDPOINT, 151 152 /** Get data from device. 153 * See explanation at usb_iface_funcs_t (IN transaction). 154 */ 155 IPC_M_USBHC_READ, 156 157 /** Send data to device. 158 * See explanation at usb_iface_funcs_t (OUT transaction). 159 */ 160 IPC_M_USBHC_WRITE, 188 161 } usbhc_iface_funcs_t; 189 162 190 163 /** Callback for outgoing transfer. */ 191 typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, 192 int, void *); 164 typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, int, void *); 193 165 194 166 /** Callback for incoming transfer. */ 195 167 typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *, 196 168 int, size_t, void *); 197 198 199 /** Out transfer processing function prototype. */200 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,201 void *, size_t,202 usbhc_iface_transfer_out_callback_t, void *);203 204 /** Setup transfer processing function prototype. @deprecated */205 typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;206 207 /** In transfer processing function prototype. */208 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,209 void *, size_t,210 usbhc_iface_transfer_in_callback_t, void *);211 169 212 170 /** USB host controller communication interface. */ … … 223 181 usb_direction_t); 224 182 225 usbhc_iface_transfer_out_t interrupt_out;226 usbhc_iface_transfer_in_t interrupt_in;183 int (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t, 184 usbhc_iface_transfer_in_callback_t, void *); 227 185 228 usbhc_iface_transfer_out_t bulk_out; 229 usbhc_iface_transfer_in_t bulk_in; 230 231 int (*control_write)(ddf_fun_t *, usb_target_t, 232 void *, size_t, void *, size_t, 233 usbhc_iface_transfer_out_callback_t, void *); 234 235 int (*control_read)(ddf_fun_t *, usb_target_t, 236 void *, size_t, void *, size_t, 237 usbhc_iface_transfer_in_callback_t, void *); 186 int (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *, 187 size_t, usbhc_iface_transfer_out_callback_t, void *); 238 188 } usbhc_iface_t; 239 189 -
uspace/lib/usb/include/usb/hc.h
r47fecbb rfd07e526 62 62 devman_handle_t *); 63 63 64 int usb_hc_get_address_by_handle(devman_handle_t);64 usb_address_t usb_hc_get_address_by_handle(devman_handle_t); 65 65 66 66 int usb_hc_find(devman_handle_t, devman_handle_t *); -
uspace/lib/usb/include/usb/usb.h
r47fecbb rfd07e526 36 36 #define LIBUSB_USB_H_ 37 37 38 #include <bool.h> 38 39 #include <sys/types.h> 39 40 #include <byteorder.h> … … 105 106 * Negative values could be used to indicate error. 106 107 */ 107 typedef int usb_address_t;108 typedef int16_t usb_address_t; 108 109 109 110 /** Default USB address. */ … … 115 116 * Negative values could be used to indicate error. 116 117 */ 117 typedef int usb_endpoint_t;118 typedef int16_t usb_endpoint_t; 118 119 119 120 /** Maximum endpoint number in USB 1.1. … … 125 126 * Pair address + endpoint is identification of transaction recipient. 126 127 */ 127 typedef struct { 128 usb_address_t address; 129 usb_endpoint_t endpoint; 128 typedef union { 129 struct { 130 usb_address_t address; 131 usb_endpoint_t endpoint; 132 } __attribute__((packed)); 133 uint32_t packed; 130 134 } usb_target_t; 135 136 /** Check USB target for allowed values (address and endpoint). 137 * 138 * @param target. 139 * @return True, if values are wihtin limits, false otherwise. 140 */ 141 static inline bool usb_target_is_valid(usb_target_t target) 142 { 143 return !(target.endpoint > 15 || target.endpoint < 0 144 || target.address >= USB11_ADDRESS_MAX || target.address < 0); 145 } 131 146 132 147 /** Compare USB targets (addresses and endpoints). -
uspace/lib/usbdev/src/pipesinit.c
r47fecbb rfd07e526 486 486 return EBADF; 487 487 488 const usb_target_t target = 489 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 488 490 #define _PACK2(high, low) (((high) << 16) + (low)) 489 491 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) … … 491 493 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 492 494 int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 493 IPC_M_USBHC_REGISTER_ENDPOINT, 494 _PACK2(pipe->wire->address, pipe->endpoint_no), 495 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 495 496 _PACK3(speed, pipe->transfer_type, pipe->direction), 496 497 _PACK2(pipe->max_packet_size, interval)); -
uspace/lib/usbdev/src/pipesio.c
r47fecbb rfd07e526 65 65 void *buffer, size_t size, size_t *size_transfered) 66 66 { 67 /* 68 * Get corresponding IPC method. 69 * In future, replace with static array of mappings 70 * transfer type -> method. 71 */ 72 usbhc_iface_funcs_t ipc_method; 73 switch (pipe->transfer_type) { 74 case USB_TRANSFER_INTERRUPT: 75 ipc_method = IPC_M_USBHC_INTERRUPT_IN; 76 break; 77 case USB_TRANSFER_BULK: 78 ipc_method = IPC_M_USBHC_BULK_IN; 79 break; 80 default: 81 return ENOTSUP; 82 } 67 /* Only interrupt and bulk transfers are supported */ 68 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 69 pipe->transfer_type != USB_TRANSFER_BULK) 70 return ENOTSUP; 71 72 const usb_target_t target = 73 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 83 74 84 75 /* Ensure serialization over the phone. */ … … 89 80 * Make call identifying target USB device and type of transfer. 90 81 */ 91 aid_t opening_request = async_send_ 3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),92 ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);82 aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_READ, target.packed, NULL); 93 84 94 85 if (opening_request == 0) { … … 213 204 void *buffer, size_t size) 214 205 { 215 /* 216 * Get corresponding IPC method. 217 * In future, replace with static array of mappings 218 * transfer type -> method. 219 */ 220 usbhc_iface_funcs_t ipc_method; 221 switch (pipe->transfer_type) { 222 case USB_TRANSFER_INTERRUPT: 223 ipc_method = IPC_M_USBHC_INTERRUPT_OUT; 224 break; 225 case USB_TRANSFER_BULK: 226 ipc_method = IPC_M_USBHC_BULK_OUT; 227 break; 228 default: 229 return ENOTSUP; 230 } 206 /* Only interrupt and bulk transfers are supported */ 207 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 208 pipe->transfer_type != USB_TRANSFER_BULK) 209 return ENOTSUP; 210 211 const usb_target_t target = 212 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 231 213 232 214 /* Ensure serialization over the phone. */ … … 238 220 */ 239 221 aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 240 ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);222 IPC_M_USBHC_WRITE, target.packed, size, NULL); 241 223 242 224 if (opening_request == 0) { … … 352 334 pipe_start_transaction(pipe); 353 335 336 const usb_target_t target = 337 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 338 339 assert(setup_buffer_size == 8); 340 uint64_t setup_packet; 341 memcpy(&setup_packet, setup_buffer, 8); 354 342 /* 355 343 * Make call identifying target USB device and control transfer type. 356 344 */ 357 345 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 358 aid_t opening_request = async_send_ 3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),359 IPC_M_USBHC_ CONTROL_READ, pipe->wire->address, pipe->endpoint_no,360 NULL);361 346 aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 347 IPC_M_USBHC_READ, target.packed, 348 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL); 349 362 350 if (opening_request == 0) { 363 351 async_exchange_end(exch); 364 352 return ENOMEM; 365 353 } 366 367 /* 368 * Send the setup packet. 369 */ 370 int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size); 371 if (rc != EOK) { 372 async_exchange_end(exch); 373 pipe_end_transaction(pipe); 374 async_wait_for(opening_request, NULL); 375 return rc; 376 } 377 354 378 355 /* 379 356 * Retrieve the data. … … 498 475 pipe_start_transaction(pipe); 499 476 477 const usb_target_t target = 478 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 479 assert(setup_buffer_size == 8); 480 uint64_t setup_packet; 481 memcpy(&setup_packet, setup_buffer, 8); 482 500 483 /* 501 484 * Make call identifying target USB device and control transfer type. 502 485 */ 503 486 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 504 aid_t opening_request = async_send_ 4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),505 IPC_M_USBHC_ CONTROL_WRITE, pipe->wire->address, pipe->endpoint_no,506 data_buffer_size, NULL);487 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 488 IPC_M_USBHC_WRITE, target.packed, data_buffer_size, 489 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL); 507 490 508 491 if (opening_request == 0) { … … 511 494 return ENOMEM; 512 495 } 513 514 /* 515 * Send the setup packet. 516 */ 517 int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size); 518 if (rc != EOK) { 519 async_exchange_end(exch); 520 pipe_end_transaction(pipe); 521 async_wait_for(opening_request, NULL); 522 return rc; 523 } 524 496 525 497 /* 526 498 * Send the data (if any). 527 499 */ 528 500 if (data_buffer_size > 0) { 529 rc = async_data_write_start(exch, data_buffer, data_buffer_size);501 int rc = async_data_write_start(exch, data_buffer, data_buffer_size); 530 502 531 503 /* All data sent, pipe can be released. */ -
uspace/lib/usbhost/Makefile
r47fecbb rfd07e526 32 32 -I$(LIBUSB_PREFIX)/include \ 33 33 -I$(LIBDRV_PREFIX)/include \ 34 -Iinclude 34 -Iinclude 35 35 36 36 SOURCES = \ 37 src/batch.c \38 src/device_keeper.c \39 37 src/endpoint.c \ 40 src/usb_endpoint_manager.c 38 src/iface.c \ 39 src/usb_device_manager.c \ 40 src/usb_endpoint_manager.c \ 41 src/usb_transfer_batch.c 41 42 42 43 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/usbhost/include/usb/host/endpoint.h
r47fecbb rfd07e526 54 54 fibril_condvar_t avail; 55 55 volatile bool active; 56 void (*destroy_hook)(struct endpoint *); 56 57 struct { 57 58 void *data; … … 68 69 69 70 void endpoint_set_hc_data(endpoint_t *instance, 70 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 void *data, void (*destroy_hook)(endpoint_t *), 72 int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 73 72 74 void endpoint_clear_hc_data(endpoint_t *instance); -
uspace/lib/usbhost/include/usb/host/usb_device_manager.h
r47fecbb rfd07e526 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup libusbhost 30 29 * @{ 31 30 */ 32 31 /** @file 33 * Device keeper structure and functions.32 * Device manager structure and functions. 34 33 * 35 34 * Typical USB host controller needs to keep track of various settings for … … 38 37 * This structure shall simplify the management. 39 38 */ 40 #ifndef LIBUSBHOST_HOST_ DEVICE_KEEPER_H41 #define LIBUSBHOST_HOST_ DEVICE_KEEPER_H39 #ifndef LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H 40 #define LIBUSBHOST_HOST_USB_DEVICE_MANAGER_H 42 41 43 42 #include <adt/list.h> … … 57 56 }; 58 57 59 /** Host controller device keeper.58 /** Host controller device manager. 60 59 * You shall not access members directly but only using functions below. 61 60 */ … … 64 63 fibril_mutex_t guard; 65 64 usb_address_t last_address; 66 } usb_device_ keeper_t;65 } usb_device_manager_t; 67 66 68 void usb_device_ keeper_init(usb_device_keeper_t *instance);67 void usb_device_manager_init(usb_device_manager_t *instance); 69 68 70 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,71 usb_ speed_t speed);69 usb_address_t usb_device_manager_get_free_address( 70 usb_device_manager_t *instance, usb_speed_t speed); 72 71 73 void usb_device_ keeper_bind(usb_device_keeper_t *instance,72 void usb_device_manager_bind(usb_device_manager_t *instance, 74 73 usb_address_t address, devman_handle_t handle); 75 74 76 void usb_device_ keeper_release(usb_device_keeper_t *instance,75 void usb_device_manager_release(usb_device_manager_t *instance, 77 76 usb_address_t address); 78 77 79 usb_address_t usb_device_ keeper_find(usb_device_keeper_t *instance,78 usb_address_t usb_device_manager_find(usb_device_manager_t *instance, 80 79 devman_handle_t handle); 81 80 82 bool usb_device_ keeper_find_by_address(usb_device_keeper_t *instance,81 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 83 82 usb_address_t address, devman_handle_t *handle); 84 83 85 usb_speed_t usb_device_ keeper_get_speed(usb_device_keeper_t *instance,84 usb_speed_t usb_device_manager_get_speed(usb_device_manager_t *instance, 86 85 usb_address_t address); 87 86 #endif -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
r47fecbb rfd07e526 38 38 */ 39 39 #ifndef LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 40 #define LIBUSBHOST_HOST_ YSB_ENDPOINT_MANAGER_H40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 42 #include <stdlib.h> … … 52 52 hash_table_t ep_table; 53 53 fibril_mutex_t guard; 54 fibril_condvar_t change;55 54 size_t free_bw; 55 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 56 56 } usb_endpoint_manager_t; 57 57 … … 60 60 61 61 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 62 size_t available_bandwidth); 62 size_t available_bandwidth, 63 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)); 63 64 64 65 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance); … … 77 78 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data); 78 79 80 /** Wrapper combining allocation and insertion */ 79 81 static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 80 82 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, -
uspace/lib/usbhost/src/endpoint.c
r47fecbb rfd07e526 53 53 instance->toggle = 0; 54 54 instance->active = false; 55 instance->destroy_hook = NULL; 56 instance->hc_data.data = NULL; 57 instance->hc_data.toggle_get = NULL; 58 instance->hc_data.toggle_set = NULL; 55 59 fibril_mutex_initialize(&instance->guard); 56 60 fibril_condvar_initialize(&instance->avail); … … 64 68 assert(instance); 65 69 assert(!instance->active); 70 if (instance->hc_data.data) { 71 assert(instance->destroy_hook); 72 instance->destroy_hook(instance); 73 } 66 74 free(instance); 67 75 } 68 76 /*----------------------------------------------------------------------------*/ 69 77 void endpoint_set_hc_data(endpoint_t *instance, 70 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 78 void *data, void (*destroy_hook)(endpoint_t *), 79 int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 71 80 { 72 81 assert(instance); 82 instance->destroy_hook = destroy_hook; 73 83 instance->hc_data.data = data; 74 84 instance->hc_data.toggle_get = toggle_get; … … 79 89 { 80 90 assert(instance); 91 instance->destroy_hook = NULL; 81 92 instance->hc_data.data = NULL; 82 93 instance->hc_data.toggle_get = NULL; -
uspace/lib/usbhost/src/usb_device_manager.c
r47fecbb rfd07e526 31 31 */ 32 32 /** @file 33 * Device keeper structure and functions (implementation).33 * Device manager structure and functions (implementation). 34 34 */ 35 35 #include <assert.h> 36 36 #include <errno.h> 37 37 #include <usb/debug.h> 38 #include <usb/host/ device_keeper.h>39 40 /*----------------------------------------------------------------------------*/ 41 /** Initialize device keeper structure.38 #include <usb/host/usb_device_manager.h> 39 40 /*----------------------------------------------------------------------------*/ 41 /** Initialize device manager structure. 42 42 * 43 43 * @param[in] instance Memory place to initialize. … … 45 45 * Set all values to false/0. 46 46 */ 47 void usb_device_ keeper_init(usb_device_keeper_t *instance)47 void usb_device_manager_init(usb_device_manager_t *instance) 48 48 { 49 49 assert(instance); … … 63 63 /** Get a free USB address 64 64 * 65 * @param[in] instance Device keeper structure to use.65 * @param[in] instance Device manager structure to use. 66 66 * @param[in] speed Speed of the device requiring address. 67 67 * @return Free address, or error code. 68 68 */ 69 usb_address_t device_keeper_get_free_address(70 usb_device_ keeper_t *instance, usb_speed_t speed)69 usb_address_t usb_device_manager_get_free_address( 70 usb_device_manager_t *instance, usb_speed_t speed) 71 71 { 72 72 assert(instance); … … 97 97 /** Bind USB address to devman handle. 98 98 * 99 * @param[in] instance Device keeper structure to use.99 * @param[in] instance Device manager structure to use. 100 100 * @param[in] address Device address 101 101 * @param[in] handle Devman handle of the device. 102 102 */ 103 void usb_device_ keeper_bind(usb_device_keeper_t *instance,103 void usb_device_manager_bind(usb_device_manager_t *instance, 104 104 usb_address_t address, devman_handle_t handle) 105 105 { … … 117 117 /** Release used USB address. 118 118 * 119 * @param[in] instance Device keeper structure to use.119 * @param[in] instance Device manager structure to use. 120 120 * @param[in] address Device address 121 121 */ 122 void usb_device_ keeper_release(123 usb_device_ keeper_t *instance, usb_address_t address)122 void usb_device_manager_release( 123 usb_device_manager_t *instance, usb_address_t address) 124 124 { 125 125 assert(instance); … … 136 136 /** Find USB address associated with the device 137 137 * 138 * @param[in] instance Device keeper structure to use.138 * @param[in] instance Device manager structure to use. 139 139 * @param[in] handle Devman handle of the device seeking its address. 140 140 * @return USB Address, or error code. 141 141 */ 142 usb_address_t usb_device_ keeper_find(143 usb_device_ keeper_t *instance, devman_handle_t handle)142 usb_address_t usb_device_manager_find( 143 usb_device_manager_t *instance, devman_handle_t handle) 144 144 { 145 145 assert(instance); … … 161 161 * Intentionally refuse to find handle of default address. 162 162 * 163 * @param[in] instance Device keeper structure to use.163 * @param[in] instance Device manager structure to use. 164 164 * @param[in] address Address the caller wants to find. 165 165 * @param[out] handle Where to store found handle. 166 166 * @return Whether such address is currently occupied. 167 167 */ 168 bool usb_device_ keeper_find_by_address(usb_device_keeper_t *instance,168 bool usb_device_manager_find_by_address(usb_device_manager_t *instance, 169 169 usb_address_t address, devman_handle_t *handle) 170 170 { … … 191 191 /** Get speed associated with the address 192 192 * 193 * @param[in] instance Device keeper structure to use.193 * @param[in] instance Device manager structure to use. 194 194 * @param[in] address Address of the device. 195 195 * @return USB speed. 196 196 */ 197 usb_speed_t usb_device_ keeper_get_speed(198 usb_device_ keeper_t *instance, usb_address_t address)197 usb_speed_t usb_device_manager_get_speed( 198 usb_device_manager_t *instance, usb_address_t address) 199 199 { 200 200 assert(instance); -
uspace/lib/usbhost/src/usb_endpoint_manager.c
r47fecbb rfd07e526 45 45 static hash_index_t node_hash(unsigned long key[]) 46 46 { 47 hash_index_t hash = 0; 48 unsigned i = 0; 49 for (;i < MAX_KEYS; ++i) { 50 hash ^= key[i]; 51 } 52 hash %= BUCKET_COUNT; 53 return hash; 47 /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1]) 48 * produces unique value for every address.endpoint pair */ 49 return ((key[0] << 4) | key[1]) % BUCKET_COUNT; 54 50 } 55 51 /*----------------------------------------------------------------------------*/ … … 63 59 switch (keys) { 64 60 case 3: 65 match = match && (key[2] == node->ep->direction); 61 match = match && 62 ((key[2] == node->ep->direction) 63 || (node->ep->direction == USB_DIRECTION_BOTH)); 66 64 case 2: 67 65 match = match && (key[1] == (unsigned long)node->ep->endpoint); … … 140 138 /*----------------------------------------------------------------------------*/ 141 139 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 142 size_t available_bandwidth) 140 size_t available_bandwidth, 141 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 143 142 { 144 143 assert(instance); 145 144 fibril_mutex_initialize(&instance->guard); 146 fibril_condvar_initialize(&instance->change);147 145 instance->free_bw = available_bandwidth; 148 bool ht = 146 instance->bw_count = bw_count; 147 const bool ht = 149 148 hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op); 150 149 return ht ? EOK : ENOMEM; … … 159 158 endpoint_t *ep, size_t data_size) 160 159 { 160 assert(instance); 161 assert(instance->bw_count); 161 162 assert(ep); 162 size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,163 const size_t bw = instance->bw_count(ep->speed, ep->transfer_type, 163 164 data_size, ep->max_packet_size); 164 assert(instance); 165 166 fibril_mutex_lock(&instance->guard); 167 168 if (bw > instance->free_bw) { 169 fibril_mutex_unlock(&instance->guard); 170 return ENOSPC; 171 } 165 172 166 173 unsigned long key[MAX_KEYS] = 167 174 {ep->address, ep->endpoint, ep->direction}; 168 fibril_mutex_lock(&instance->guard); 169 170 link_t *item = 175 176 const link_t *item = 171 177 hash_table_find(&instance->ep_table, key); 172 178 if (item != NULL) { 173 179 fibril_mutex_unlock(&instance->guard); 174 180 return EEXISTS; 175 }176 177 if (bw > instance->free_bw) {178 fibril_mutex_unlock(&instance->guard);179 return ENOSPC;180 181 } 181 182 … … 193 194 instance->free_bw -= bw; 194 195 fibril_mutex_unlock(&instance->guard); 195 fibril_condvar_broadcast(&instance->change);196 196 return EOK; 197 197 } … … 211 211 212 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active) 213 if (node->ep->active) { 214 fibril_mutex_unlock(&instance->guard); 214 215 return EBUSY; 216 } 215 217 216 218 instance->free_bw += node->bw; … … 218 220 219 221 fibril_mutex_unlock(&instance->guard); 220 fibril_condvar_broadcast(&instance->change);221 222 return EOK; 222 223 } … … 230 231 231 232 fibril_mutex_lock(&instance->guard); 232 link_t *item = hash_table_find(&instance->ep_table, key);233 const link_t *item = hash_table_find(&instance->ep_table, key); 233 234 if (item == NULL) { 234 235 fibril_mutex_unlock(&instance->guard); 235 236 return NULL; 236 237 } 237 node_t *node = hash_table_get_instance(item, node_t, link);238 const node_t *node = hash_table_get_instance(item, node_t, link); 238 239 if (bw) 239 240 *bw = node->bw; … … 255 256 { 256 257 assert(instance); 257 if (target.endpoint > 15 || target.endpoint < 0 258 || target.address >= USB11_ADDRESS_MAX || target.address < 0) { 258 if (!usb_target_is_valid(target)) { 259 259 usb_log_error("Invalid data when checking for toggle reset.\n"); 260 260 return; 261 261 } 262 262 263 assert(data); 263 264 switch (data[1]) 264 265 { 265 case 0x01: /* clear feature*/266 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */266 case 0x01: /* Clear Feature -- resets only cleared ep */ 267 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */ 267 268 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 268 269 /* endpoint number is < 16, thus first byte is enough */ … … 276 277 break; 277 278 278 case 0x9: /* set configuration */279 case 0x11: /* set interface */280 /* target must be device */279 case 0x9: /* Set Configuration */ 280 case 0x11: /* Set Interface */ 281 /* Recipient must be device */ 281 282 if ((data[0] & 0xf) == 0) { 282 283 usb_target_t reset_target = -
uspace/lib/usbhost/src/usb_transfer_batch.c
r47fecbb rfd07e526 37 37 #include <usb/usb.h> 38 38 #include <usb/debug.h> 39 #include <usb/host/batch.h> 39 #include <usb/host/usb_transfer_batch.h> 40 #include <usb/host/hcd.h> 40 41 41 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 42 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 43 44 void usb_transfer_batch_init( 45 usb_transfer_batch_t *instance, 42 usb_transfer_batch_t * usb_transfer_batch_get( 46 43 endpoint_t *ep, 47 44 char *buffer, 48 char *data_buffer,49 45 size_t buffer_size, 50 char *setup_buffer, 51 size_t setup_size, 46 uint64_t setup_buffer, 52 47 usbhc_iface_transfer_in_callback_t func_in, 53 48 usbhc_iface_transfer_out_callback_t func_out, … … 55 50 ddf_fun_t *fun, 56 51 void *private_data, 57 void (*private_data_dtor)(void * p_data)52 void (*private_data_dtor)(void *) 58 53 ) 59 54 { 60 assert(instance); 61 link_initialize(&instance->link); 62 instance->ep = ep; 63 instance->callback_in = func_in; 64 instance->callback_out = func_out; 65 instance->arg = arg; 66 instance->buffer = buffer; 67 instance->data_buffer = data_buffer; 68 instance->buffer_size = buffer_size; 69 instance->setup_buffer = setup_buffer; 70 instance->setup_size = setup_size; 71 instance->fun = fun; 72 instance->private_data = private_data; 73 instance->private_data_dtor = private_data_dtor; 74 instance->transfered_size = 0; 75 instance->next_step = NULL; 76 instance->error = EOK; 77 endpoint_use(instance->ep); 55 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 56 if (instance) { 57 instance->ep = ep; 58 instance->callback_in = func_in; 59 instance->callback_out = func_out; 60 instance->arg = arg; 61 instance->buffer = buffer; 62 instance->buffer_size = buffer_size; 63 instance->setup_size = 0; 64 instance->fun = fun; 65 instance->private_data = private_data; 66 instance->private_data_dtor = private_data_dtor; 67 instance->transfered_size = 0; 68 instance->error = EOK; 69 if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) { 70 memcpy(instance->setup_buffer, &setup_buffer, 71 USB_SETUP_PACKET_SIZE); 72 instance->setup_size = USB_SETUP_PACKET_SIZE; 73 } 74 if (instance->ep) 75 endpoint_use(instance->ep); 76 } 77 return instance; 78 78 } 79 79 /*----------------------------------------------------------------------------*/ 80 /** Helper function, calls callback and correctly destroys batch structure.80 /** Mark batch as finished and run callback. 81 81 * 82 82 * @param[in] instance Batch structure to use. 83 * @param[in] data Data to copy to the output buffer. 84 * @param[in] size Size of @p data. 83 85 */ 84 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance) 85 { 86 assert(instance); 87 usb_transfer_batch_call_in(instance); 88 usb_transfer_batch_dispose(instance); 89 } 90 /*----------------------------------------------------------------------------*/ 91 /** Helper function calls callback and correctly destroys batch structure. 92 * 93 * @param[in] instance Batch structure to use. 94 */ 95 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance) 96 { 97 assert(instance); 98 usb_transfer_batch_call_out(instance); 99 usb_transfer_batch_dispose(instance); 100 } 101 /*----------------------------------------------------------------------------*/ 102 /** Mark batch as finished and continue with next step. 103 * 104 * @param[in] instance Batch structure to use. 105 * 106 */ 107 void usb_transfer_batch_finish(usb_transfer_batch_t *instance) 86 void usb_transfer_batch_finish( 87 usb_transfer_batch_t *instance, const void *data, size_t size) 108 88 { 109 89 assert(instance); 110 90 assert(instance->ep); 111 assert(instance->next_step); 112 endpoint_release(instance->ep); 113 instance->next_step(instance); 91 /* we care about the data and there are some to copy */ 92 if (instance->ep->direction != USB_DIRECTION_OUT 93 && data) { 94 const size_t min_size = 95 size < instance->buffer_size ? size : instance->buffer_size; 96 memcpy(instance->buffer, data, min_size); 97 } 98 if (instance->callback_out) 99 usb_transfer_batch_call_out(instance); 100 if (instance->callback_in) 101 usb_transfer_batch_call_in(instance); 102 114 103 } 115 104 /*----------------------------------------------------------------------------*/ … … 124 113 assert(instance); 125 114 assert(instance->callback_in); 126 assert(instance->ep);127 128 /* We are data in, we need data */129 memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);130 115 131 116 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n", … … 150 135 str_error(instance->error)); 151 136 137 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 138 && instance->error == EOK) { 139 const usb_target_t target = 140 {{ instance->ep->address, instance->ep->endpoint }}; 141 reset_ep_if_need( 142 fun_to_hcd(instance->fun), target, instance->setup_buffer); 143 } 144 152 145 instance->callback_out(instance->fun, 153 146 instance->error, instance->arg); … … 160 153 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance) 161 154 { 162 assert(instance); 155 if (!instance) 156 return; 163 157 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n", 164 158 instance, USB_TRANSFER_BATCH_ARGS(*instance)); 159 if (instance->ep) { 160 endpoint_release(instance->ep); 161 } 165 162 if (instance->private_data) { 166 163 assert(instance->private_data_dtor);
Note:
See TracChangeset
for help on using the changeset viewer.
