Changeset e50cd7f in mainline for uspace/lib
- Timestamp:
- 2011-04-17T19:17:55Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 63517c2, cfbbe1d3
- Parents:
- ef354b6 (diff), 8595577b (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:
-
- 10 added
- 46 edited
-
c/arch/mips32/include/atomic.h (modified) (1 diff)
-
c/generic/adt/measured_strings.c (modified) (1 diff)
-
c/generic/async.c (modified) (2 diffs)
-
c/generic/vfs/vfs.c (modified) (2 diffs)
-
c/include/async.h (modified) (2 diffs)
-
c/include/ipc/dev_iface.h (modified) (1 diff)
-
drv/generic/dev_iface.c (modified) (2 diffs)
-
drv/generic/driver.c (modified) (4 diffs)
-
drv/generic/remote_usbhc.c (modified) (12 diffs)
-
drv/generic/remote_usbhid.c (added)
-
drv/include/remote_usbhid.h (added)
-
drv/include/usbhc_iface.h (modified) (7 diffs)
-
drv/include/usbhid_iface.h (added)
-
net/generic/generic.c (modified) (4 diffs)
-
net/generic/net_checksum.c (modified) (6 diffs)
-
net/generic/packet_client.c (modified) (2 diffs)
-
net/il/ip_client.c (modified) (4 diffs)
-
net/tl/icmp_client.c (modified) (1 diff)
-
net/tl/socket_core.c (modified) (21 diffs)
-
net/tl/tl_common.c (modified) (6 diffs)
-
packet/generic/packet_server.c (modified) (2 diffs)
-
softint/generic/multiplication.c (modified) (1 diff)
-
usb/Makefile (modified) (2 diffs)
-
usb/include/usb/classes/hid/iface.h (added)
-
usb/include/usb/classes/hidparser.h (modified) (1 diff)
-
usb/include/usb/classes/hub.h (modified) (3 diffs)
-
usb/include/usb/classes/massstor.h (added)
-
usb/include/usb/devdrv.h (modified) (1 diff)
-
usb/include/usb/devpoll.h (added)
-
usb/include/usb/host/batch.h (modified) (3 diffs)
-
usb/include/usb/host/device_keeper.h (modified) (3 diffs)
-
usb/include/usb/host/endpoint.h (modified) (3 diffs)
-
usb/include/usb/host/usb_endpoint_manager.h (modified) (2 diffs)
-
usb/include/usb/hub.h (modified) (1 diff)
-
usb/include/usb/pipes.h (modified) (5 diffs)
-
usb/include/usb/request.h (modified) (2 diffs)
-
usb/include/usb/usb.h (modified) (1 diff)
-
usb/src/altiface.c (added)
-
usb/src/devdrv.c (modified) (7 diffs)
-
usb/src/devpoll.c (modified) (10 diffs)
-
usb/src/hidiface.c (added)
-
usb/src/hidparser.c (modified) (4 diffs)
-
usb/src/hidreport.c (modified) (3 diffs)
-
usb/src/hidreq.c (modified) (17 diffs)
-
usb/src/host/batch.c (modified) (6 diffs)
-
usb/src/host/device_keeper.c (modified) (6 diffs)
-
usb/src/host/endpoint.c (modified) (5 diffs)
-
usb/src/host/usb_endpoint_manager.c (modified) (4 diffs)
-
usb/src/hub.c (modified) (8 diffs)
-
usb/src/pipepriv.c (added)
-
usb/src/pipepriv.h (added)
-
usb/src/pipes.c (modified) (6 diffs)
-
usb/src/pipesinit.c (modified) (6 diffs)
-
usb/src/pipesio.c (modified) (19 diffs)
-
usb/src/recognise.c (modified) (1 diff)
-
usb/src/request.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/arch/mips32/include/atomic.h
ref354b6 re50cd7f 70 70 " sc %0, %1\n" 71 71 " beq %0, %4, 1b\n" /* if the atomic operation failed, try again */ 72 /* nop */ /* nop is inserted automatically by compiler */73 72 " nop\n" 74 73 : "=&r" (tmp), -
uspace/lib/c/generic/adt/measured_strings.c
ref354b6 re50cd7f 74 74 new->length = length; 75 75 new->value = ((uint8_t *) new) + sizeof(measured_string_t); 76 / / append terminating zero explicitly - to be safe76 /* Append terminating zero explicitly - to be safe */ 77 77 memcpy(new->value, string, new->length); 78 78 new->value[new->length] = '\0'; -
uspace/lib/c/generic/async.c
ref354b6 re50cd7f 1586 1586 * @param dst Address of the beginning of the destination buffer. 1587 1587 * @param size Size of the destination buffer. 1588 * @param flags Flags to control the data transfer. 1588 1589 * 1589 1590 * @return Zero on success or a negative error code from errno.h. 1590 1591 * 1591 1592 */ 1592 int async_data_read_start(int phoneid, void *dst, size_t size) 1593 { 1594 return async_req_2_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst, 1595 (sysarg_t) size); 1593 int 1594 async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags) 1595 { 1596 return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst, 1597 (sysarg_t) size, (sysarg_t) flags); 1596 1598 } 1597 1599 … … 1683 1685 * @param src Address of the beginning of the source buffer. 1684 1686 * @param size Size of the source buffer. 1687 * @param flags Flags to control the data transfer. 1685 1688 * 1686 1689 * @return Zero on success or a negative error code from errno.h. 1687 1690 * 1688 1691 */ 1689 int async_data_write_start(int phoneid, const void *src, size_t size) 1690 { 1691 return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src, 1692 (sysarg_t) size); 1692 int 1693 async_data_write_start_generic(int phoneid, const void *src, size_t size, 1694 int flags) 1695 { 1696 return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src, 1697 (sysarg_t) size, (sysarg_t) flags); 1693 1698 } 1694 1699 -
uspace/lib/c/generic/vfs/vfs.c
ref354b6 re50cd7f 378 378 379 379 req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer); 380 rc = async_data_read_start(vfs_phone, (void *)buf, nbyte); 380 rc = async_data_read_start_generic(vfs_phone, (void *) buf, nbyte, 381 IPC_XF_RESTRICT); 381 382 if (rc != EOK) { 382 383 vfs_exchange_end(vfs_phone); … … 407 408 408 409 req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer); 409 rc = async_data_write_start(vfs_phone, (void *)buf, nbyte); 410 rc = async_data_write_start_generic(vfs_phone, (void *) buf, nbyte, 411 IPC_XF_RESTRICT); 410 412 if (rc != EOK) { 411 413 vfs_exchange_end(vfs_phone); -
uspace/lib/c/include/async.h
ref354b6 re50cd7f 341 341 342 342 extern aid_t async_data_read(int, void *, size_t, ipc_call_t *); 343 extern int async_data_read_start(int, void *, size_t); 343 #define async_data_read_start(p, buf, len) \ 344 async_data_read_start_generic((p), (buf), (len), IPC_XF_NONE) 345 346 extern int async_data_read_start_generic(int, void *, size_t, int); 344 347 extern bool async_data_read_receive(ipc_callid_t *, size_t *); 345 348 extern int async_data_read_finalize(ipc_callid_t, const void *, size_t); … … 380 383 (arg4), (answer)) 381 384 382 extern int async_data_write_start(int, const void *, size_t); 385 #define async_data_write_start(p, buf, len) \ 386 async_data_write_start_generic((p), (buf), (len), IPC_XF_NONE) 387 388 extern int async_data_write_start_generic(int, const void *, size_t, int); 383 389 extern bool async_data_write_receive(ipc_callid_t *, size_t *); 384 390 extern int async_data_write_finalize(ipc_callid_t, void *, size_t); -
uspace/lib/c/include/ipc/dev_iface.h
ref354b6 re50cd7f 45 45 /** Interface provided by USB host controller. */ 46 46 USBHC_DEV_IFACE, 47 /** Interface provided by USB HID devices. */ 48 USBHID_DEV_IFACE, 47 49 48 50 DEV_IFACE_MAX -
uspace/lib/drv/generic/dev_iface.c
ref354b6 re50cd7f 43 43 #include "remote_usb.h" 44 44 #include "remote_usbhc.h" 45 #include "remote_usbhid.h" 45 46 #include "remote_pci.h" 46 47 … … 51 52 &remote_pci_iface, 52 53 &remote_usb_iface, 53 &remote_usbhc_iface 54 &remote_usbhc_iface, 55 &remote_usbhid_iface 54 56 } 55 57 }; -
uspace/lib/drv/generic/driver.c
ref354b6 re50cd7f 47 47 #include <stdlib.h> 48 48 #include <str.h> 49 #include <str_error.h> 49 50 #include <ctype.h> 50 51 #include <errno.h> … … 402 403 get_remote_method(rem_iface, iface_method_idx); 403 404 if (iface_method_ptr == NULL) { 404 / / the interface has not such method405 /* The interface has not such method */ 405 406 printf("%s: driver_connection_gen error - " 406 407 "invalid interface method.", driver->name); … … 655 656 int ddf_driver_main(driver_t *drv) 656 657 { 658 int rc; 659 657 660 /* 658 661 * Remember the driver structure - driver_ops will be called by generic … … 668 671 669 672 /* 670 * Register driver by device manager with generic handler for incoming671 * connections.673 * Register driver with device manager using generic handler for 674 * incoming connections. 672 675 */ 673 devman_driver_register(driver->name, driver_connection); 674 676 rc = devman_driver_register(driver->name, driver_connection); 677 if (rc != EOK) { 678 printf("Error: Failed to register driver with device manager " 679 "(%s).\n", (rc == EEXISTS) ? "driver already started" : 680 str_error(rc)); 681 682 return 1; 683 } 684 685 /* Return success from the task since server has started. */ 686 rc = task_retval(0); 687 if (rc != EOK) 688 return 1; 689 675 690 async_manager(); 676 691 -
uspace/lib/drv/generic/remote_usbhc.c
ref354b6 re50cd7f 50 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 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 52 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 55 53 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 61 59 /** Remote USB host controller interface operations. */ 62 60 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 63 remote_usbhc_reserve_default_address,64 remote_usbhc_release_default_address,65 66 61 remote_usbhc_request_address, 67 62 remote_usbhc_bind_address, … … 129 124 } 130 125 131 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,132 ipc_callid_t callid, ipc_call_t *call)133 {134 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;135 136 if (!usb_iface->reserve_default_address) {137 async_answer_0(callid, ENOTSUP);138 return;139 }140 141 usb_speed_t speed = DEV_IPC_GET_ARG1(*call);142 143 int rc = usb_iface->reserve_default_address(fun, speed);144 145 async_answer_0(callid, rc);146 }147 148 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,149 ipc_callid_t callid, ipc_call_t *call)150 {151 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;152 153 if (!usb_iface->release_default_address) {154 async_answer_0(callid, ENOTSUP);155 return;156 }157 158 int rc = usb_iface->release_default_address(fun);159 160 async_answer_0(callid, rc);161 }162 163 126 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 164 127 ipc_callid_t callid, ipc_call_t *call) … … 270 233 } 271 234 272 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);273 235 usb_target_t target = { 274 236 .address = DEV_IPC_GET_ARG1(*call), … … 300 262 trans->size = len; 301 263 302 rc = transfer_func(fun, target, max_packet_size,264 rc = transfer_func(fun, target, 303 265 buffer, len, 304 266 callback_out, trans); … … 326 288 } 327 289 328 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);329 290 usb_target_t target = { 330 291 .address = DEV_IPC_GET_ARG1(*call), … … 348 309 trans->size = len; 349 310 350 int rc = transfer_func(fun, target, max_packet_size,311 int rc = transfer_func(fun, target, 351 312 trans->buffer, len, 352 313 callback_in, trans); … … 414 375 }; 415 376 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call); 416 size_t max_packet_size = DEV_IPC_GET_ARG4(*call);417 377 418 378 int rc; … … 450 410 trans->size = data_buffer_len; 451 411 452 rc = usb_iface->control_write(fun, target, max_packet_size,412 rc = usb_iface->control_write(fun, target, 453 413 setup_packet, setup_packet_len, 454 414 data_buffer, data_buffer_len, … … 477 437 .endpoint = DEV_IPC_GET_ARG2(*call) 478 438 }; 479 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);480 439 481 440 int rc; … … 515 474 } 516 475 517 rc = usb_iface->control_read(fun, target, max_packet_size,476 rc = usb_iface->control_read(fun, target, 518 477 setup_packet, setup_packet_len, 519 478 trans->buffer, trans->size, … … 537 496 } 538 497 539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \ 540 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256 541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \ 542 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256 543 544 INIT_FROM_HIGH_DATA(usb_address_t, address, 1); 545 INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1); 546 INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2); 547 INIT_FROM_LOW_DATA(usb_direction_t, direction, 2); 548 549 #undef INIT_FROM_HIGH_DATA 550 #undef INIT_FROM_LOW_DATA 551 552 size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call); 553 unsigned int interval = (unsigned int) DEV_IPC_GET_ARG4(*call); 554 555 int rc = usb_iface->register_endpoint(fun, address, endpoint, 498 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \ 499 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 500 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \ 501 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16) 502 #define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \ 503 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 504 #define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \ 505 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8) 506 #define _INIT_FROM_LOW_DATA3(type, var, arg_no) \ 507 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 508 509 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 510 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 511 512 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); 513 _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2); 514 _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2); 515 516 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3); 517 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3); 518 519 #undef _INIT_FROM_HIGH_DATA2 520 #undef _INIT_FROM_LOW_DATA2 521 #undef _INIT_FROM_HIGH_DATA3 522 #undef _INIT_FROM_MIDDLE_DATA3 523 #undef _INIT_FROM_LOW_DATA3 524 525 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint, 556 526 transfer_type, direction, max_packet_size, interval); 557 527 -
uspace/lib/drv/include/usbhc_iface.h
ref354b6 re50cd7f 66 66 * - argument #1 is target address 67 67 * - argument #2 is target endpoint 68 * - argument #3 is max packet size of the endpoint69 68 * - this call is immediately followed by IPC data read (async version) 70 69 * - the call is not answered until the device returns some data (or until … … 85 84 */ 86 85 typedef enum { 87 /** Reserve usage of default address.88 * This call informs the host controller that the caller will be89 * using default USB address. It is duty of the HC driver to ensure90 * that only single entity will have it reserved.91 * The address is returned via IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS.92 * The caller can start using the address after receiving EOK93 * answer.94 */95 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS,96 97 /** Release usage of default address.98 * @see IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS99 */100 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS,101 102 86 /** Asks for address assignment by host controller. 103 87 * Answer: … … 169 153 /** Register endpoint attributes at host controller. 170 154 * This is used to reserve portion of USB bandwidth. 155 * When speed is invalid, speed of the device is used. 171 156 * Parameters: 172 * - USB address + endpoint number (ADDR * 256 + EP) 173 * - transfer type + direction (TYPE * 256 + DIR) 174 * - maximum packet size 175 * - interval (in milliseconds) 157 * - USB address + endpoint number 158 * - packed as ADDR << 16 + EP 159 * - speed + transfer type + direction 160 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 161 * - maximum packet size + interval (in milliseconds) 162 * - packed as MPS << 16 + INT 176 163 * Answer: 177 164 * - EOK - reservation successful … … 202 189 203 190 /** Out transfer processing function prototype. */ 204 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,191 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, 205 192 void *, size_t, 206 193 usbhc_iface_transfer_out_callback_t, void *); … … 210 197 211 198 /** In transfer processing function prototype. */ 212 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,199 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, 213 200 void *, size_t, 214 201 usbhc_iface_transfer_in_callback_t, void *); … … 222 209 int (*release_address)(ddf_fun_t *, usb_address_t); 223 210 224 int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, 211 int (*register_endpoint)(ddf_fun_t *, 212 usb_address_t, usb_speed_t, usb_endpoint_t, 225 213 usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 226 214 int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, … … 234 222 235 223 int (*control_write)(ddf_fun_t *, usb_target_t, 236 size_t,237 224 void *, size_t, void *, size_t, 238 225 usbhc_iface_transfer_out_callback_t, void *); 239 226 240 227 int (*control_read)(ddf_fun_t *, usb_target_t, 241 size_t,242 228 void *, size_t, void *, size_t, 243 229 usbhc_iface_transfer_in_callback_t, void *); -
uspace/lib/net/generic/generic.c
ref354b6 re50cd7f 106 106 return EBADMEM; 107 107 108 / / request the address108 /* Request the address */ 109 109 message_id = async_send_1(phone, (sysarg_t) message, 110 110 (sysarg_t) device_id, NULL); … … 112 112 async_wait_for(message_id, &result); 113 113 114 / / if not successful114 /* If not successful */ 115 115 if ((string == EOK) && (result != EOK)) { 116 / / clear the data116 /* Clear the data */ 117 117 free(*address); 118 118 free(*data); … … 242 242 return EBADMEM; 243 243 244 / / request the translation244 /* Request the translation */ 245 245 message_id = async_send_3(phone, (sysarg_t) message, 246 246 (sysarg_t) device_id, (sysarg_t) count, (sysarg_t) service, NULL); … … 249 249 async_wait_for(message_id, &result); 250 250 251 / / if not successful251 /* If not successful */ 252 252 if ((string == EOK) && (result != EOK)) { 253 / / clear the data253 /* Clear the data */ 254 254 free(*translation); 255 255 free(*data); -
uspace/lib/net/generic/net_checksum.c
ref354b6 re50cd7f 52 52 uint16_t compact_checksum(uint32_t sum) 53 53 { 54 / / shorten to the 16 bits54 /* Shorten to the 16 bits */ 55 55 while (sum >> 16) 56 56 sum = (sum & 0xffff) + (sum >> 16); … … 72 72 size_t index; 73 73 74 / / sum all the 16 bit fields74 /* Sum all the 16 bit fields */ 75 75 for (index = 0; index + 1 < length; index += 2) 76 76 seed += (data[index] << 8) + data[index + 1]; 77 77 78 / / last odd byte with zero padding78 /* Last odd byte with zero padding */ 79 79 if (index + 1 == length) 80 80 seed += data[index] << 8; … … 94 94 size_t index; 95 95 96 / / process full bytes96 /* Process full bytes */ 97 97 while (length >= 8) { 98 / / add the data98 /* Add the data */ 99 99 seed ^= (*data) << 24; 100 100 101 / / for each added bit101 /* For each added bit */ 102 102 for (index = 0; index < 8; ++index) { 103 / / if the first bit is set103 /* If the first bit is set */ 104 104 if (seed & 0x80000000) { 105 / / shift and divide the checksum105 /* Shift and divide the checksum */ 106 106 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 107 107 } else { 108 / / shift otherwise108 /* Shift otherwise */ 109 109 seed <<= 1; 110 110 } 111 111 } 112 112 113 / / move to the next byte113 /* Move to the next byte */ 114 114 ++data; 115 115 length -= 8; 116 116 } 117 117 118 / / process the odd bits118 /* Process the odd bits */ 119 119 if (length > 0) { 120 / / add the data with zero padding120 /* Add the data with zero padding */ 121 121 seed ^= ((*data) & (0xff << (8 - length))) << 24; 122 122 123 / / for each added bit123 /* For each added bit */ 124 124 for (index = 0; index < length; ++index) { 125 / / if the first bit is set125 /* If the first bit is set */ 126 126 if (seed & 0x80000000) { 127 / / shift and divide the checksum127 /* Shift and divide the checksum */ 128 128 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE); 129 129 } else { 130 / / shift otherwise130 /* Shift otherwise */ 131 131 seed <<= 1; 132 132 } … … 148 148 size_t index; 149 149 150 / / process full bytes150 /* Process full bytes */ 151 151 while (length >= 8) { 152 / / add the data152 /* Add the data */ 153 153 seed ^= (*data); 154 154 155 / / for each added bit155 /* For each added bit */ 156 156 for (index = 0; index < 8; ++index) { 157 / / if the last bit is set157 /* If the last bit is set */ 158 158 if (seed & 1) { 159 / / shift and divide the checksum159 /* Shift and divide the checksum */ 160 160 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 161 161 } else { 162 / / shift otherwise162 /* Shift otherwise */ 163 163 seed >>= 1; 164 164 } 165 165 } 166 166 167 / / move to the next byte167 /* Move to the next byte */ 168 168 ++data; 169 169 length -= 8; 170 170 } 171 171 172 / / process the odd bits172 /* Process the odd bits */ 173 173 if (length > 0) { 174 / / add the data with zero padding174 /* Add the data with zero padding */ 175 175 seed ^= (*data) >> (8 - length); 176 176 177 177 for (index = 0; index < length; ++index) { 178 / / if the last bit is set178 /* If the last bit is set */ 179 179 if (seed & 1) { 180 / / shift and divide the checksum180 /* Shift and divide the checksum */ 181 181 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE); 182 182 } else { 183 / / shift otherwise183 /* Shift otherwise */ 184 184 seed >>= 1; 185 185 } … … 198 198 uint16_t flip_checksum(uint16_t checksum) 199 199 { 200 / / flip, zero is returned as 0xFFFF (not flipped)200 /* Flip, zero is returned as 0xFFFF (not flipped) */ 201 201 checksum = ~checksum; 202 202 return checksum ? checksum : IP_CHECKSUM_ZERO; … … 216 216 uint16_t ip_checksum(uint8_t *data, size_t length) 217 217 { 218 / / compute, compact and flip the data checksum218 /* Compute, compact and flip the data checksum */ 219 219 return flip_checksum(compact_checksum(compute_checksum(0, data, 220 220 length))); -
uspace/lib/net/generic/packet_client.c
ref354b6 re50cd7f 267 267 return NULL; 268 268 269 / / get a new packet269 /* Get a new packet */ 270 270 copy = packet_get_4_remote(phone, PACKET_DATA_LENGTH(packet), 271 271 PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix, … … 274 274 return NULL; 275 275 276 / / get addresses276 /* Get addresses */ 277 277 addrlen = packet_get_addr(packet, &src, &dest); 278 / / copy data278 /* Copy data */ 279 279 if ((packet_copy_data(copy, packet_get_data(packet), 280 280 PACKET_DATA_LENGTH(packet)) == EOK) && 281 / / copy addresses if present281 /* Copy addresses if present */ 282 282 ((addrlen <= 0) || 283 283 (packet_set_addr(copy, src, dest, addrlen) == EOK))) { -
uspace/lib/net/il/ip_client.c
ref354b6 re50cd7f 124 124 125 125 // TODO IPv6 126 /* case AF_INET6: 126 #if 0 127 case AF_INET6: 127 128 if (addrlen != sizeof(struct sockaddr_in6)) 128 129 return EINVAL; … … 130 131 address_in6 = (struct sockaddr_in6 *) addr; 131 132 return EOK; 132 */ 133 #endif 133 134 134 135 default: … … 159 160 size_t padding; 160 161 161 // compute the padding if IP options are set 162 // multiple of 4 bytes 162 /* 163 * Compute the padding if IP options are set 164 * multiple of 4 bytes 165 */ 163 166 padding = ipopt_length % 4; 164 167 if (padding) { … … 167 170 } 168 171 169 / / prefix the header172 /* Prefix the header */ 170 173 data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding); 171 174 if (!data) 172 175 return ENOMEM; 173 176 174 / / add the padding177 /* Add the padding */ 175 178 while (padding--) 176 179 data[sizeof(ip_header_t) + padding] = IPOPT_NOOP; 177 180 178 / / set the header181 /* Set the header */ 179 182 header = (ip_header_t *) data; 180 183 header->header_length = IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) + -
uspace/lib/net/tl/icmp_client.c
ref354b6 re50cd7f 81 81 *mtu = header->un.frag.mtu; 82 82 83 / / remove debug dump83 /* Remove debug dump */ 84 84 #ifdef CONFIG_DEBUG 85 85 printf("ICMP error %d (%d) in packet %d\n", header->type, header->code, -
uspace/lib/net/tl/socket_core.c
ref354b6 re50cd7f 91 91 int packet_id; 92 92 93 / / if bound93 /* If bound */ 94 94 if (socket->port) { 95 / / release the port95 /* Release the port */ 96 96 socket_port_release(global_sockets, socket); 97 97 } 98 98 99 / / release all received packets99 /* Release all received packets */ 100 100 while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0) 101 101 pq_release_remote(packet_phone, packet_id); … … 166 166 int rc; 167 167 168 / / create a wrapper168 /* Create a wrapper */ 169 169 socket_ref = malloc(sizeof(*socket_ref)); 170 170 if (!socket_ref) … … 172 172 173 173 *socket_ref = socket; 174 / / add the wrapper174 /* Add the wrapper */ 175 175 rc = socket_port_map_add(&socket_port->map, key, key_length, 176 176 socket_ref); … … 206 206 int rc; 207 207 208 / / create a wrapper208 /* Create a wrapper */ 209 209 socket_port = malloc(sizeof(*socket_port)); 210 210 if (!socket_port) … … 221 221 goto fail; 222 222 223 / / register the incomming port223 /* Register the incoming port */ 224 224 rc = socket_ports_add(global_sockets, port, socket_port); 225 225 if (rc < 0) … … 277 277 278 278 address_in = (struct sockaddr_in *) addr; 279 / / find the socket279 /* Find the socket */ 280 280 socket = socket_cores_find(local_sockets, socket_id); 281 281 if (!socket) 282 282 return ENOTSOCK; 283 283 284 / / bind a free port?284 /* Bind a free port? */ 285 285 if (address_in->sin_port <= 0) 286 286 return socket_bind_free_port(global_sockets, socket, 287 287 free_ports_start, free_ports_end, last_used_port); 288 288 289 / / try to find the port289 /* Try to find the port */ 290 290 socket_port = socket_ports_find(global_sockets, 291 291 ntohs(address_in->sin_port)); 292 292 if (socket_port) { 293 / / already used293 /* Already used */ 294 294 return EADDRINUSE; 295 295 } 296 296 297 / / if bound297 /* If bound */ 298 298 if (socket->port) { 299 / / release the port299 /* Release the port */ 300 300 socket_port_release(global_sockets, socket); 301 301 } … … 333 333 int index; 334 334 335 / / from the last used one335 /* From the last used one */ 336 336 index = last_used_port; 337 337 … … 339 339 ++index; 340 340 341 / / til the range end341 /* Till the range end */ 342 342 if (index >= free_ports_end) { 343 / / start from the range beginning343 /* Start from the range beginning */ 344 344 index = free_ports_start - 1; 345 345 do { 346 346 ++index; 347 / / til the last used one347 /* Till the last used one */ 348 348 if (index >= last_used_port) { 349 / / none found349 /* None found */ 350 350 return ENOTCONN; 351 351 } 352 352 } while (socket_ports_find(global_sockets, index)); 353 353 354 / / found, break immediately354 /* Found, break immediately */ 355 355 break; 356 356 } … … 376 376 377 377 count = 0; 378 // socket_id = socket_globals.last_id; 378 #if 0 379 socket_id = socket_globals.last_id; 380 #endif 379 381 do { 380 382 if (count < SOCKET_ID_TRIES) { … … 384 386 socket_id = 1; 385 387 ++count; 386 / / only this branch for last_id388 /* Only this branch for last_id */ 387 389 } else { 388 390 if (socket_id < INT_MAX) { 389 391 ++ socket_id; 390 /* } else if(socket_globals.last_id) { 391 * socket_globals.last_id = 0; 392 * socket_id = 1; 393 */ } else { 392 #if 0 393 } else if(socket_globals.last_id) { 394 socket_globals.last_id = 0; 395 socket_id = 1; 396 #endif 397 } else { 394 398 return ELIMIT; 395 399 } … … 425 429 return EINVAL; 426 430 427 / / store the socket431 /* Store the socket */ 428 432 if (*socket_id <= 0) { 429 433 positive = (*socket_id == 0); … … 441 445 return ENOMEM; 442 446 443 / / initialize447 /* Initialize */ 444 448 socket->phone = app_phone; 445 449 socket->port = -1; … … 493 497 int accepted_id; 494 498 495 / / find the socket499 /* Find the socket */ 496 500 socket = socket_cores_find(local_sockets, socket_id); 497 501 if (!socket) 498 502 return ENOTSOCK; 499 503 500 / / destroy all accepted sockets504 /* Destroy all accepted sockets */ 501 505 while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0) 502 506 socket_destroy(packet_phone, accepted_id, local_sockets, … … 535 539 next_packet = pq_next(packet); 536 540 if (!next_packet) { 537 / / write all if only one fragment541 /* Write all if only one fragment */ 538 542 rc = data_reply(packet_get_data(packet), 539 543 packet_get_data_length(packet)); 540 544 if (rc != EOK) 541 545 return rc; 542 / / store the total length546 /* Store the total length */ 543 547 *length = packet_get_data_length(packet); 544 548 } else { 545 / / count the packet fragments549 /* Count the packet fragments */ 546 550 fragments = 1; 547 551 next_packet = pq_next(packet); … … 549 553 ++fragments; 550 554 551 / / compute and store the fragment lengths555 /* Compute and store the fragment lengths */ 552 556 lengths = (size_t *) malloc(sizeof(size_t) * fragments + 553 557 sizeof(size_t)); … … 565 569 } 566 570 567 / / write the fragment lengths571 /* Write the fragment lengths */ 568 572 rc = data_reply(lengths, sizeof(int) * (fragments + 1)); 569 573 if (rc != EOK) { … … 573 577 next_packet = packet; 574 578 575 / / write the fragments579 /* Write the fragments */ 576 580 for (index = 0; index < fragments; ++index) { 577 581 rc = data_reply(packet_get_data(next_packet), … … 584 588 } 585 589 586 / / store the total length590 /* Store the total length */ 587 591 *length = lengths[fragments]; 588 592 free(lengths); … … 636 640 return; 637 641 638 / / find ports642 /* Find ports */ 639 643 socket_port = socket_ports_find(global_sockets, socket->port); 640 644 if (socket_port) { 641 / / find the socket645 /* Find the socket */ 642 646 socket_ref = socket_port_map_find(&socket_port->map, 643 647 socket->key, socket->key_length); … … 646 650 --socket_port->count; 647 651 648 / / release if empty652 /* Release if empty */ 649 653 if (socket_port->count <= 0) { 650 / / destroy the map654 /* Destroy the map */ 651 655 socket_port_map_destroy(&socket_port->map, free); 652 / / release the port656 /* Release the port */ 653 657 socket_ports_exclude(global_sockets, 654 658 socket->port, free); 655 659 } else { 656 / / remove660 /* Remove */ 657 661 socket_port_map_exclude(&socket_port->map, 658 662 socket->key, socket->key_length, free); … … 685 689 int rc; 686 690 687 / / find ports691 /* Find ports */ 688 692 socket_port = socket_ports_find(global_sockets, port); 689 693 if (!socket_port) 690 694 return ENOENT; 691 695 692 / / add the socket696 /* Add the socket */ 693 697 rc = socket_port_add_core(socket_port, socket, key, key_length); 694 698 if (rc != EOK) -
uspace/lib/net/tl/tl_common.c
ref354b6 re50cd7f 255 255 int length; 256 256 257 / / detach the first packet and release the others257 /* Detach the first packet and release the others */ 258 258 next = pq_detach(packet); 259 259 if (next) … … 262 262 length = packet_get_addr(packet, &src, NULL); 263 263 if ((length > 0) && (!error) && (icmp_phone >= 0) && 264 // set both addresses to the source one (avoids the source address 265 // deletion before setting the destination one) 264 /* 265 * Set both addresses to the source one (avoids the source address 266 * deletion before setting the destination one) 267 */ 266 268 (packet_set_addr(packet, src, src, (size_t) length) == EOK)) { 267 269 return EOK; … … 299 301 return EINVAL; 300 302 301 / / get the data length303 /* Get the data length */ 302 304 if (!async_data_write_receive(&callid, &length)) 303 305 return EINVAL; 304 306 305 / / get a new packet307 /* Get a new packet */ 306 308 *packet = packet_get_4_remote(packet_phone, length, dimension->addr_len, 307 309 prefix + dimension->prefix, dimension->suffix); … … 309 311 return ENOMEM; 310 312 311 / / allocate space in the packet313 /* Allocate space in the packet */ 312 314 data = packet_suffix(*packet, length); 313 315 if (!data) { … … 316 318 } 317 319 318 / / read the data into the packet320 /* Read the data into the packet */ 319 321 rc = async_data_write_finalize(callid, data, length); 320 322 if (rc != EOK) { … … 323 325 } 324 326 325 / / set the packet destination address327 /* Set the packet destination address */ 326 328 rc = packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen); 327 329 if (rc != EOK) { -
uspace/lib/packet/generic/packet_server.c
ref354b6 re50cd7f 112 112 size_t max_content, size_t max_suffix) 113 113 { 114 / / clear the packet content114 /* Clear the packet content */ 115 115 bzero(((void *) packet) + sizeof(packet_t), 116 116 packet->length - sizeof(packet_t)); 117 117 118 / / clear the packet header118 /* Clear the packet header */ 119 119 packet->order = 0; 120 120 packet->metric = 0; … … 151 151 assert(fibril_mutex_is_locked(&ps_globals.lock)); 152 152 153 / / already locked153 /* Already locked */ 154 154 packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE, 155 155 MAP_SHARED | MAP_ANONYMOUS, 0, 0); -
uspace/lib/softint/generic/multiplication.c
ref354b6 re50cd7f 109 109 * result does not fit in signed one */ 110 110 if (SOFTINT_CHECK_OF && ((t2 < t1) || (t2 & (1ull << 63)))) { 111 / / error, overflow111 /* Error, overflow */ 112 112 return (neg ? INT64_MIN : INT64_MAX); 113 113 } -
uspace/lib/usb/Makefile
ref354b6 re50cd7f 34 34 SOURCES = \ 35 35 src/addrkeep.c \ 36 src/altiface.c \ 36 37 src/class.c \ 37 38 src/ddfiface.c \ … … 41 42 src/dp.c \ 42 43 src/dump.c \ 44 src/hidiface.c \ 43 45 src/hidparser.c \ 44 46 src/hub.c \ 47 src/pipepriv.c \ 45 48 src/pipes.c \ 46 49 src/pipesinit.c \ -
uspace/lib/usb/include/usb/classes/hidparser.h
ref354b6 re50cd7f 317 317 usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path); 318 318 319 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type); 319 320 320 321 /* -
uspace/lib/usb/include/usb/classes/hub.h
ref354b6 re50cd7f 43 43 */ 44 44 typedef enum { 45 USB_HUB_FEATURE_HUB_LOCAL_POWER = 0, 46 USB_HUB_FEATURE_HUB_OVER_CURRENT = 1, 45 47 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0, 46 48 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1, … … 59 61 /* USB_HUB_FEATURE_ = , */ 60 62 } usb_hub_class_feature_t; 63 61 64 62 65 /** Header of standard hub descriptor without the "variadic" part. */ … … 149 152 maximum of 255 ports). 150 153 */ 151 uint8_t * devices_removable;154 uint8_t devices_removable[32]; 152 155 153 156 /** -
uspace/lib/usb/include/usb/devdrv.h
ref354b6 re50cd7f 162 162 usb_endpoint_description_t **); 163 163 164 typedef bool (*usb_polling_callback_t)(usb_device_t *, 165 uint8_t *, size_t, void *); 166 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *); 164 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *); 165 int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *, 166 usb_endpoint_description_t **, uint8_t *, size_t, int, int, 167 usb_endpoint_mapping_t **, size_t *); 168 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 169 int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **); 167 170 168 int usb_device_auto_poll(usb_device_t *, size_t, 169 usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *); 171 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t); 172 int usb_alternate_interfaces_create(uint8_t *, size_t, int, 173 usb_alternate_interfaces_t **); 170 174 171 175 #endif -
uspace/lib/usb/include/usb/host/batch.h
ref354b6 re50cd7f 43 43 typedef struct usb_transfer_batch usb_transfer_batch_t; 44 44 struct usb_transfer_batch { 45 endpoint_t *ep; 45 46 link_t link; 46 usb_target_t target;47 usb_transfer_type_t transfer_type;48 usb_speed_t speed;49 usb_direction_t direction;50 47 usbhc_iface_transfer_in_callback_t callback_in; 51 48 usbhc_iface_transfer_out_callback_t callback_out; 49 void *arg; 52 50 char *buffer; 53 char * transport_buffer;51 char *data_buffer; 54 52 size_t buffer_size; 55 53 char *setup_buffer; 56 54 size_t setup_size; 57 size_t max_packet_size;58 55 size_t transfered_size; 59 56 void (*next_step)(usb_transfer_batch_t *); 60 57 int error; 61 58 ddf_fun_t *fun; 62 void *arg;63 endpoint_t *ep;64 59 void *private_data; 60 void (*private_data_dtor)(void *p_data); 65 61 }; 66 62 67 63 void usb_transfer_batch_init( 68 64 usb_transfer_batch_t *instance, 69 usb_target_t target, 70 usb_transfer_type_t transfer_type, 71 usb_speed_t speed, 72 size_t max_packet_size, 65 endpoint_t *ep, 73 66 char *buffer, 74 char * transport_buffer,67 char *data_buffer, 75 68 size_t buffer_size, 76 69 char *setup_buffer, … … 80 73 void *arg, 81 74 ddf_fun_t *fun, 82 endpoint_t *ep,83 void *private_data75 void *private_data, 76 void (*private_data_dtor)(void *p_data) 84 77 ); 78 79 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance); 80 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance); 81 void usb_transfer_batch_finish(usb_transfer_batch_t *instance); 82 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance); 83 84 static inline void usb_transfer_batch_finish_error( 85 usb_transfer_batch_t *instance, int error) 86 { 87 assert(instance); 88 instance->error = error; 89 usb_transfer_batch_finish(instance); 90 } 85 91 86 92 static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l) … … 90 96 } 91 97 92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error);95 96 98 #endif 97 99 /** -
uspace/lib/usb/include/usb/host/device_keeper.h
ref354b6 re50cd7f 54 54 usb_speed_t speed; 55 55 bool occupied; 56 link_t endpoints;57 uint16_t control_used;58 56 devman_handle_t handle; 59 57 }; … … 65 63 struct usb_device_info devices[USB_ADDRESS_COUNT]; 66 64 fibril_mutex_t guard; 67 fibril_condvar_t change;68 65 usb_address_t last_address; 69 66 } usb_device_keeper_t; 70 67 71 68 void usb_device_keeper_init(usb_device_keeper_t *instance); 72 73 void usb_device_keeper_add_ep(74 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);75 76 void usb_device_keeper_reserve_default_address(77 usb_device_keeper_t *instance, usb_speed_t speed);78 79 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance);80 81 void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,82 usb_target_t target, const uint8_t *setup_data);83 69 84 70 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance, … … 96 82 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance, 97 83 usb_address_t address); 98 99 void usb_device_keeper_use_control(usb_device_keeper_t *instance,100 usb_target_t target);101 102 void usb_device_keeper_release_control(usb_device_keeper_t *instance,103 usb_target_t target);104 105 84 #endif 106 85 /** -
uspace/lib/usb/include/usb/host/endpoint.h
ref354b6 re50cd7f 39 39 #include <bool.h> 40 40 #include <adt/list.h> 41 #include <fibril_synch.h> 42 41 43 #include <usb/usb.h> 42 44 … … 48 50 usb_speed_t speed; 49 51 size_t max_packet_size; 50 bool active;51 52 unsigned toggle:1; 52 link_t same_device_eps; 53 fibril_mutex_t guard; 54 fibril_condvar_t avail; 55 volatile bool active; 56 struct { 57 void *data; 58 int (*toggle_get)(void *); 59 void (*toggle_set)(void *, int); 60 } hc_data; 53 61 } endpoint_t; 54 62 … … 59 67 void endpoint_destroy(endpoint_t *instance); 60 68 69 void endpoint_set_hc_data(endpoint_t *instance, 70 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 72 void endpoint_clear_hc_data(endpoint_t *instance); 73 74 void endpoint_use(endpoint_t *instance); 75 76 void endpoint_release(endpoint_t *instance); 77 61 78 int endpoint_toggle_get(endpoint_t *instance); 62 79 63 80 void endpoint_toggle_set(endpoint_t *instance, int toggle); 64 81 65 void endpoint_toggle_reset(link_t *ep); 66 67 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn); 68 82 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 69 83 #endif 70 84 /** -
uspace/lib/usb/include/usb/host/usb_endpoint_manager.h
ref354b6 re50cd7f 66 66 endpoint_t *ep, size_t data_size); 67 67 68 int usb_endpoint_manager_register_ep_wait(usb_endpoint_manager_t *instance,69 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,70 void *data, void (*data_remove_callback)(void* data, void* arg), void *arg,71 size_t bw);72 73 68 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 74 69 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction); … … 78 73 size_t *bw); 79 74 75 void usb_endpoint_manager_reset_if_need( 76 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data); 77 78 static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance, 79 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 80 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 81 size_t data_size) 82 { 83 endpoint_t *ep = malloc(sizeof(endpoint_t)); 84 if (ep == NULL) 85 return ENOMEM; 86 87 int ret = endpoint_init(ep, address, endpoint, direction, type, speed, 88 max_packet_size); 89 if (ret != EOK) { 90 free(ep); 91 return ret; 92 } 93 94 ret = usb_endpoint_manager_register_ep(instance, ep, data_size); 95 if (ret != EOK) { 96 endpoint_destroy(ep); 97 return ret; 98 } 99 return EOK; 100 } 80 101 #endif 81 102 /** -
uspace/lib/usb/include/usb/hub.h
ref354b6 re50cd7f 59 59 } usb_hc_attached_device_t; 60 60 61 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);62 int usb_hc_release_default_address(usb_hc_connection_t *);63 64 61 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t); 65 62 int usb_hc_register_device(usb_hc_connection_t *, -
uspace/lib/usb/include/usb/pipes.h
ref354b6 re50cd7f 42 42 #include <ipc/devman.h> 43 43 #include <ddf/driver.h> 44 #include <fibril_synch.h> 44 45 45 46 /** Abstraction of a physical connection to the device. … … 59 60 * This endpoint must be bound with existing usb_device_connection_t 60 61 * (i.e. the wire to send data over). 62 * 63 * Locking order: if you want to lock both mutexes 64 * (@c guard and @c hc_phone_mutex), lock @c guard first. 65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex 66 * only. 61 67 */ 62 68 typedef struct { 69 /** Guard of the whole pipe. */ 70 fibril_mutex_t guard; 71 63 72 /** The connection used for sending the data. */ 64 73 usb_device_connection_t *wire; … … 78 87 /** Phone to the host controller. 79 88 * Negative when no session is active. 89 * It is an error to access this member without @c hc_phone_mutex 90 * being locked. 91 * If call over the phone is to be made, it must be preceeded by 92 * call to pipe_add_ref() [internal libusb function]. 80 93 */ 81 94 int hc_phone; 95 96 /** Guard for serialization of requests over the phone. */ 97 fibril_mutex_t hc_phone_mutex; 98 99 /** Number of active transfers over the pipe. */ 100 int refcount; 101 102 /** Whether to automatically reset halt on the endpoint. 103 * Valid only for control endpoint zero. 104 */ 105 bool auto_reset_halt; 82 106 } usb_pipe_t; 83 107 … … 134 158 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 135 159 size_t, uint8_t *, size_t, usb_device_connection_t *); 160 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t, 161 unsigned int, usb_hc_connection_t *); 136 162 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *); 137 163 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *); … … 140 166 int usb_pipe_end_session(usb_pipe_t *); 141 167 bool usb_pipe_is_session_started(usb_pipe_t *); 168 169 int usb_pipe_start_long_transfer(usb_pipe_t *); 170 void usb_pipe_end_long_transfer(usb_pipe_t *); 142 171 143 172 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usb/include/usb/request.h
ref354b6 re50cd7f 50 50 /** USB endpoint status - endpoint is halted (stalled). */ 51 51 #define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0)) 52 53 /** USB feature selector - endpoint halt (stall). */ 54 #define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0) 55 56 /** USB feature selector - device remote wake-up. */ 57 #define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1) 52 58 53 59 /** Standard device request. */ … … 135 141 char **); 136 142 143 int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t); 144 137 145 #endif 138 146 /** -
uspace/lib/usb/include/usb/usb.h
ref354b6 re50cd7f 77 77 USB_SPEED_FULL, 78 78 /** USB 2.0 high speed (480Mbits/s). */ 79 USB_SPEED_HIGH 79 USB_SPEED_HIGH, 80 /** Psuedo-speed serving as a boundary. */ 81 USB_SPEED_MAX 80 82 } usb_speed_t; 81 83 -
uspace/lib/usb/src/devdrv.c
ref354b6 re50cd7f 72 72 } 73 73 74 /** Log out of memory error on given device.75 *76 * @param dev Device causing the trouble.77 */78 static void usb_log_oom(ddf_dev_t *dev)79 {80 usb_log_error("Out of memory when adding device `%s'.\n",81 dev->name);82 }83 84 74 /** Count number of pipes the driver expects. 85 75 * … … 108 98 */ 109 99 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 111 { 112 int rc; 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 100 usb_device_t *dev, int alternate_setting) 101 { 102 if (endpoints == NULL) { 103 dev->pipes = NULL; 104 dev->pipes_count = 0; 116 105 return EOK; 117 106 } 118 107 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 120 if (dev->pipes == NULL) { 121 usb_log_oom(dev->ddf_dev); 122 return ENOMEM; 123 } 124 125 size_t i; 126 127 /* Initialize to NULL first for rollback purposes. */ 128 for (i = 0; i < pipe_count; i++) { 129 dev->pipes[i].pipe = NULL; 130 } 131 132 for (i = 0; i < pipe_count; i++) { 133 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 134 if (dev->pipes[i].pipe == NULL) { 135 usb_log_oom(dev->ddf_dev); 136 rc = ENOMEM; 137 goto rollback; 138 } 139 140 dev->pipes[i].description = endpoints[i]; 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 143 } 144 145 rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count, 108 usb_endpoint_mapping_t *pipes; 109 size_t pipes_count; 110 111 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 146 112 dev->descriptors.configuration, dev->descriptors.configuration_size, 147 &dev->wire); 148 if (rc != EOK) { 149 usb_log_error("Failed initializing USB endpoints: %s.\n", 150 str_error(rc)); 151 goto rollback; 152 } 153 154 /* Register the endpoints. */ 155 usb_hc_connection_t hc_conn; 156 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 157 if (rc != EOK) { 158 usb_log_error( 159 "Failed initializing connection to host controller: %s.\n", 160 str_error(rc)); 161 goto rollback; 162 } 163 rc = usb_hc_connection_open(&hc_conn); 164 if (rc != EOK) { 165 usb_log_error("Failed to connect to host controller: %s.\n", 166 str_error(rc)); 167 goto rollback; 168 } 169 for (i = 0; i < pipe_count; i++) { 170 if (dev->pipes[i].present) { 171 rc = usb_pipe_register(dev->pipes[i].pipe, 172 dev->pipes[i].descriptor->poll_interval, 173 &hc_conn); 174 /* Ignore error when operation not supported by HC. */ 175 if ((rc != EOK) && (rc != ENOTSUP)) { 176 /* FIXME: what shall we do? */ 177 dev->pipes[i].present = false; 178 free(dev->pipes[i].pipe); 179 dev->pipes[i].pipe = NULL; 180 } 181 } 182 } 183 /* Ignoring errors here. */ 184 usb_hc_connection_close(&hc_conn); 185 186 dev->pipes_count = pipe_count; 187 188 return EOK; 189 190 rollback: 191 for (i = 0; i < pipe_count; i++) { 192 if (dev->pipes[i].pipe != NULL) { 193 free(dev->pipes[i].pipe); 194 } 195 } 196 free(dev->pipes); 197 198 return rc; 199 } 200 201 /** Initialize all endpoint pipes. 202 * 203 * @param drv The driver. 204 * @param dev The device to be initialized. 205 * @return Error code. 206 */ 207 static int initialize_pipes(usb_device_t *dev) 208 { 209 int rc; 210 211 rc = usb_device_connection_initialize_from_device(&dev->wire, 212 dev->ddf_dev); 213 if (rc != EOK) { 214 usb_log_error( 215 "Failed initializing connection on device `%s'. %s.\n", 216 dev->ddf_dev->name, str_error(rc)); 217 return rc; 218 } 219 220 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 221 &dev->wire); 222 if (rc != EOK) { 223 usb_log_error("Failed to initialize default control pipe " \ 224 "on device `%s': %s.\n", 225 dev->ddf_dev->name, str_error(rc)); 226 return rc; 227 } 228 229 rc = usb_pipe_probe_default_control(&dev->ctrl_pipe); 230 if (rc != EOK) { 231 usb_log_error( 232 "Probing default control pipe on device `%s' failed: %s.\n", 233 dev->ddf_dev->name, str_error(rc)); 234 return rc; 235 } 236 237 /* Get our interface. */ 238 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 239 240 /* 241 * For further actions, we need open session on default control pipe. 242 */ 243 rc = usb_pipe_start_session(&dev->ctrl_pipe); 244 if (rc != EOK) { 245 usb_log_error("Failed to start an IPC session: %s.\n", 246 str_error(rc)); 247 return rc; 248 } 249 250 /* Get the device descriptor. */ 251 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, 252 &dev->descriptors.device); 253 if (rc != EOK) { 254 usb_log_error("Failed to retrieve device descriptor: %s.\n", 255 str_error(rc)); 256 return rc; 257 } 258 259 /* Get the full configuration descriptor. */ 260 rc = usb_request_get_full_configuration_descriptor_alloc( 261 &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration, 262 &dev->descriptors.configuration_size); 263 if (rc != EOK) { 264 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n", 265 dev->ddf_dev->name, str_error(rc)); 266 return rc; 267 } 268 269 if (driver->endpoints != NULL) { 270 rc = initialize_other_pipes(driver->endpoints, dev); 271 } 272 273 /* No checking here. */ 274 usb_pipe_end_session(&dev->ctrl_pipe); 275 276 /* Rollback actions. */ 277 if (rc != EOK) { 278 if (dev->descriptors.configuration != NULL) { 279 free(dev->descriptors.configuration); 280 } 281 } 282 283 return rc; 284 } 285 286 /** Count number of alternate settings of a interface. 287 * 288 * @param config_descr Full configuration descriptor. 289 * @param config_descr_size Size of @p config_descr in bytes. 290 * @param interface_no Interface number. 291 * @return Number of alternate interfaces for @p interface_no interface. 292 */ 293 static size_t count_alternate_interfaces(uint8_t *config_descr, 294 size_t config_descr_size, int interface_no) 295 { 296 assert(config_descr != NULL); 297 usb_dp_parser_t dp_parser = { 298 .nesting = usb_dp_standard_descriptor_nesting 299 }; 300 usb_dp_parser_data_t dp_data = { 301 .data = config_descr, 302 .size = config_descr_size, 303 .arg = NULL 304 }; 305 306 size_t alternate_count = 0; 307 308 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 309 &dp_data, config_descr); 310 while (iface_ptr != NULL) { 311 usb_standard_interface_descriptor_t *iface 312 = (usb_standard_interface_descriptor_t *) iface_ptr; 313 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) { 314 if (iface->interface_number == interface_no) { 315 alternate_count++; 316 } 317 } 318 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 319 config_descr, iface_ptr); 320 } 321 322 return alternate_count; 323 } 324 325 /** Initialize structures related to alternate interfaces. 326 * 327 * @param dev Device where alternate settings shall be initialized. 328 * @return Error code. 329 */ 330 static int initialize_alternate_interfaces(usb_device_t *dev) 331 { 332 if (dev->interface_no < 0) { 333 dev->alternate_interfaces = NULL; 334 return EOK; 335 } 336 337 usb_alternate_interfaces_t *alternates 338 = malloc(sizeof(usb_alternate_interfaces_t)); 339 340 if (alternates == NULL) { 341 return ENOMEM; 342 } 343 344 alternates->alternative_count 345 = count_alternate_interfaces(dev->descriptors.configuration, 346 dev->descriptors.configuration_size, dev->interface_no); 347 348 if (alternates->alternative_count == 0) { 349 free(alternates); 350 return ENOENT; 351 } 352 353 alternates->alternatives = malloc(alternates->alternative_count 354 * sizeof(usb_alternate_interface_descriptors_t)); 355 if (alternates->alternatives == NULL) { 356 free(alternates); 357 return ENOMEM; 358 } 359 360 alternates->current = 0; 361 362 usb_dp_parser_t dp_parser = { 363 .nesting = usb_dp_standard_descriptor_nesting 364 }; 365 usb_dp_parser_data_t dp_data = { 366 .data = dev->descriptors.configuration, 367 .size = dev->descriptors.configuration_size, 368 .arg = NULL 369 }; 370 371 usb_alternate_interface_descriptors_t *cur_alt_iface 372 = &alternates->alternatives[0]; 373 374 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 375 &dp_data, dp_data.data); 376 while (iface_ptr != NULL) { 377 usb_standard_interface_descriptor_t *iface 378 = (usb_standard_interface_descriptor_t *) iface_ptr; 379 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) 380 || (iface->interface_number != dev->interface_no)) { 381 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 382 &dp_data, 383 dp_data.data, iface_ptr); 384 continue; 385 } 386 387 cur_alt_iface->interface = iface; 388 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface); 389 390 /* Find next interface to count size of nested descriptors. */ 391 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 392 dp_data.data, iface_ptr); 393 if (iface_ptr == NULL) { 394 uint8_t *next = dp_data.data + dp_data.size; 395 cur_alt_iface->nested_descriptors_size 396 = next - cur_alt_iface->nested_descriptors; 397 } else { 398 cur_alt_iface->nested_descriptors_size 399 = iface_ptr - cur_alt_iface->nested_descriptors; 400 } 401 402 cur_alt_iface++; 403 } 404 405 dev->alternate_interfaces = alternates; 113 dev->interface_no, alternate_setting, 114 &pipes, &pipes_count); 115 116 if (rc != EOK) { 117 return rc; 118 } 119 120 dev->pipes = pipes; 121 dev->pipes_count = pipes_count; 406 122 407 123 return EOK; … … 423 139 int rc; 424 140 425 usb_device_t *dev = malloc(sizeof(usb_device_t)); 426 if (dev == NULL) { 427 usb_log_error("Out of memory when adding device `%s'.\n", 428 gen_dev->name); 429 return ENOMEM; 430 } 431 432 433 dev->ddf_dev = gen_dev; 434 dev->ddf_dev->driver_data = dev; 435 dev->driver_data = NULL; 436 dev->descriptors.configuration = NULL; 437 438 dev->pipes_count = 0; 439 dev->pipes = NULL; 440 441 rc = initialize_pipes(dev); 442 if (rc != EOK) { 443 free(dev); 444 return rc; 445 } 446 447 (void) initialize_alternate_interfaces(dev); 141 usb_device_t *dev = NULL; 142 const char *err_msg = NULL; 143 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg); 144 if (rc != EOK) { 145 usb_log_error("USB device `%s' creation failed (%s): %s.\n", 146 gen_dev->name, err_msg, str_error(rc)); 147 return rc; 148 } 448 149 449 150 return driver->ops->add_device(dev); … … 457 158 static int destroy_current_pipes(usb_device_t *dev) 458 159 { 459 size_t i; 460 int rc; 461 462 /* TODO: this shall be done under some device mutex. */ 463 464 /* First check that no session is opened. */ 465 for (i = 0; i < dev->pipes_count; i++) { 466 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 467 return EBUSY; 468 } 469 } 470 471 /* Prepare connection to HC. */ 472 usb_hc_connection_t hc_conn; 473 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 474 if (rc != EOK) { 475 return rc; 476 } 477 rc = usb_hc_connection_open(&hc_conn); 478 if (rc != EOK) { 479 return rc; 480 } 481 482 /* Destroy the pipes. */ 483 for (i = 0; i < dev->pipes_count; i++) { 484 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 485 free(dev->pipes[i].pipe); 486 } 487 488 usb_hc_connection_close(&hc_conn); 489 490 free(dev->pipes); 160 int rc = usb_device_destroy_pipes(dev->ddf_dev, 161 dev->pipes, dev->pipes_count); 162 if (rc != EOK) { 163 return rc; 164 } 165 491 166 dev->pipes = NULL; 492 167 dev->pipes_count = 0; … … 505 180 * with usb_pipe_initialize_from_configuration(). 506 181 * 182 * @warning This is a wrapper function that does several operations that 183 * can fail and that cannot be rollbacked easily. That means that a failure 184 * during the SET_INTERFACE request would result in having a device with 185 * no pipes at all (except the default control one). That is because the old 186 * pipes needs to be unregistered at HC first and the new ones could not 187 * be created. 188 * 507 189 * @param dev USB device. 508 190 * @param alternate_setting Alternate setting to choose. … … 519 201 int rc; 520 202 521 /* TODO: more transactional behavior. */522 523 203 /* Destroy existing pipes. */ 524 204 rc = destroy_current_pipes(dev); … … 535 215 536 216 /* Create new pipes. */ 537 rc = initialize_other_pipes(endpoints, dev );217 rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting); 538 218 539 219 return rc; 220 } 221 222 /** Retrieve basic descriptors from the device. 223 * 224 * @param[in] ctrl_pipe Control endpoint pipe. 225 * @param[out] descriptors Where to store the descriptors. 226 * @return Error code. 227 */ 228 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe, 229 usb_device_descriptors_t *descriptors) 230 { 231 assert(descriptors != NULL); 232 233 descriptors->configuration = NULL; 234 235 int rc; 236 237 /* It is worth to start a long transfer. */ 238 rc = usb_pipe_start_long_transfer(ctrl_pipe); 239 if (rc != EOK) { 240 return rc; 241 } 242 243 /* Get the device descriptor. */ 244 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 245 if (rc != EOK) { 246 goto leave; 247 } 248 249 /* Get the full configuration descriptor. */ 250 rc = usb_request_get_full_configuration_descriptor_alloc( 251 ctrl_pipe, 0, (void **) &descriptors->configuration, 252 &descriptors->configuration_size); 253 254 leave: 255 usb_pipe_end_long_transfer(ctrl_pipe); 256 257 return rc; 258 } 259 260 /** Create pipes for a device. 261 * 262 * This is more or less a wrapper that does following actions: 263 * - allocate and initialize pipes 264 * - map endpoints to the pipes based on the descriptions 265 * - registers endpoints with the host controller 266 * 267 * @param[in] dev Generic DDF device backing the USB one. 268 * @param[in] wire Initialized backing connection to the host controller. 269 * @param[in] endpoints Endpoints description, NULL terminated. 270 * @param[in] config_descr Configuration descriptor of active configuration. 271 * @param[in] config_descr_size Size of @p config_descr in bytes. 272 * @param[in] interface_no Interface to map from. 273 * @param[in] interface_setting Interface setting (default is usually 0). 274 * @param[out] pipes_ptr Where to store array of created pipes 275 * (not NULL terminated). 276 * @param[out] pipes_count_ptr Where to store number of pipes 277 * (set to if you wish to ignore the count). 278 * @return Error code. 279 */ 280 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire, 281 usb_endpoint_description_t **endpoints, 282 uint8_t *config_descr, size_t config_descr_size, 283 int interface_no, int interface_setting, 284 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) 285 { 286 assert(dev != NULL); 287 assert(wire != NULL); 288 assert(endpoints != NULL); 289 assert(config_descr != NULL); 290 assert(config_descr_size > 0); 291 assert(pipes_ptr != NULL); 292 293 size_t i; 294 int rc; 295 296 size_t pipe_count = count_other_pipes(endpoints); 297 if (pipe_count == 0) { 298 *pipes_ptr = NULL; 299 return EOK; 300 } 301 302 usb_endpoint_mapping_t *pipes 303 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 304 if (pipes == NULL) { 305 return ENOMEM; 306 } 307 308 /* Initialize to NULL to allow smooth rollback. */ 309 for (i = 0; i < pipe_count; i++) { 310 pipes[i].pipe = NULL; 311 } 312 313 /* Now allocate and fully initialize. */ 314 for (i = 0; i < pipe_count; i++) { 315 pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 316 if (pipes[i].pipe == NULL) { 317 rc = ENOMEM; 318 goto rollback_free_only; 319 } 320 pipes[i].description = endpoints[i]; 321 pipes[i].interface_no = interface_no; 322 pipes[i].interface_setting = interface_setting; 323 } 324 325 /* Find the mapping from configuration descriptor. */ 326 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count, 327 config_descr, config_descr_size, wire); 328 if (rc != EOK) { 329 goto rollback_free_only; 330 } 331 332 /* Register the endpoints with HC. */ 333 usb_hc_connection_t hc_conn; 334 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 335 if (rc != EOK) { 336 goto rollback_free_only; 337 } 338 339 rc = usb_hc_connection_open(&hc_conn); 340 if (rc != EOK) { 341 goto rollback_free_only; 342 } 343 344 for (i = 0; i < pipe_count; i++) { 345 if (pipes[i].present) { 346 rc = usb_pipe_register(pipes[i].pipe, 347 pipes[i].descriptor->poll_interval, &hc_conn); 348 if (rc != EOK) { 349 goto rollback_unregister_endpoints; 350 } 351 } 352 } 353 354 usb_hc_connection_close(&hc_conn); 355 356 *pipes_ptr = pipes; 357 if (pipes_count_ptr != NULL) { 358 *pipes_count_ptr = pipe_count; 359 } 360 361 return EOK; 362 363 /* 364 * Jump here if something went wrong after endpoints have 365 * been registered. 366 * This is also the target when the registration of 367 * endpoints fails. 368 */ 369 rollback_unregister_endpoints: 370 for (i = 0; i < pipe_count; i++) { 371 if (pipes[i].present) { 372 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 373 } 374 } 375 376 usb_hc_connection_close(&hc_conn); 377 378 /* 379 * Jump here if something went wrong before some actual communication 380 * with HC. Then the only thing that needs to be done is to free 381 * allocated memory. 382 */ 383 rollback_free_only: 384 for (i = 0; i < pipe_count; i++) { 385 if (pipes[i].pipe != NULL) { 386 free(pipes[i].pipe); 387 } 388 } 389 free(pipes); 390 391 return rc; 392 } 393 394 /** Destroy pipes previously created by usb_device_create_pipes. 395 * 396 * @param[in] dev Generic DDF device backing the USB one. 397 * @param[in] pipes Endpoint mapping to be destroyed. 398 * @param[in] pipes_count Number of endpoints. 399 */ 400 int usb_device_destroy_pipes(ddf_dev_t *dev, 401 usb_endpoint_mapping_t *pipes, size_t pipes_count) 402 { 403 assert(dev != NULL); 404 assert(((pipes != NULL) && (pipes_count > 0)) 405 || ((pipes == NULL) && (pipes_count == 0))); 406 407 if (pipes_count == 0) { 408 return EOK; 409 } 410 411 int rc; 412 413 /* Prepare connection to HC to allow endpoint unregistering. */ 414 usb_hc_connection_t hc_conn; 415 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 416 if (rc != EOK) { 417 return rc; 418 } 419 rc = usb_hc_connection_open(&hc_conn); 420 if (rc != EOK) { 421 return rc; 422 } 423 424 /* Destroy the pipes. */ 425 size_t i; 426 for (i = 0; i < pipes_count; i++) { 427 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 428 free(pipes[i].pipe); 429 } 430 431 usb_hc_connection_close(&hc_conn); 432 433 free(pipes); 434 435 return EOK; 436 } 437 438 /** Initialize control pipe in a device. 439 * 440 * @param dev USB device in question. 441 * @param errmsg Where to store error context. 442 * @return 443 */ 444 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg) 445 { 446 int rc; 447 448 rc = usb_device_connection_initialize_from_device(&dev->wire, 449 dev->ddf_dev); 450 if (rc != EOK) { 451 *errmsg = "device connection initialization"; 452 return rc; 453 } 454 455 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 456 &dev->wire); 457 if (rc != EOK) { 458 *errmsg = "default control pipe initialization"; 459 return rc; 460 } 461 462 return EOK; 463 } 464 465 466 /** Create new instance of USB device. 467 * 468 * @param[in] ddf_dev Generic DDF device backing the USB one. 469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none). 470 * @param[out] dev_ptr Where to store pointer to the new device. 471 * @param[out] errstr_ptr Where to store description of context 472 * (in case error occurs). 473 * @return Error code. 474 */ 475 int usb_device_create(ddf_dev_t *ddf_dev, 476 usb_endpoint_description_t **endpoints, 477 usb_device_t **dev_ptr, const char **errstr_ptr) 478 { 479 assert(dev_ptr != NULL); 480 assert(ddf_dev != NULL); 481 482 int rc; 483 484 usb_device_t *dev = malloc(sizeof(usb_device_t)); 485 if (dev == NULL) { 486 *errstr_ptr = "structure allocation"; 487 return ENOMEM; 488 } 489 490 // FIXME: proper deallocation in case of errors 491 492 dev->ddf_dev = ddf_dev; 493 dev->driver_data = NULL; 494 dev->descriptors.configuration = NULL; 495 dev->alternate_interfaces = NULL; 496 497 dev->pipes_count = 0; 498 dev->pipes = NULL; 499 500 /* Initialize backing wire and control pipe. */ 501 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr); 502 if (rc != EOK) { 503 return rc; 504 } 505 506 /* Get our interface. */ 507 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 508 509 /* Retrieve standard descriptors. */ 510 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 511 &dev->descriptors); 512 if (rc != EOK) { 513 *errstr_ptr = "descriptor retrieval"; 514 return rc; 515 } 516 517 /* Create alternate interfaces. */ 518 rc = usb_alternate_interfaces_create(dev->descriptors.configuration, 519 dev->descriptors.configuration_size, dev->interface_no, 520 &dev->alternate_interfaces); 521 if (rc != EOK) { 522 /* We will try to silently ignore this. */ 523 dev->alternate_interfaces = NULL; 524 } 525 526 rc = initialize_other_pipes(endpoints, dev, 0); 527 if (rc != EOK) { 528 *errstr_ptr = "pipes initialization"; 529 return rc; 530 } 531 532 *errstr_ptr = NULL; 533 *dev_ptr = dev; 534 535 return EOK; 540 536 } 541 537 -
uspace/lib/usb/src/devpoll.c
ref354b6 re50cd7f 33 33 * USB device driver framework - automatic interrupt polling. 34 34 */ 35 #include <usb/dev drv.h>35 #include <usb/devpoll.h> 36 36 #include <usb/request.h> 37 37 #include <usb/debug.h> 38 #include <usb/classes/classes.h> 38 39 #include <errno.h> 39 40 #include <str_error.h> … … 45 46 /** Data needed for polling. */ 46 47 typedef struct { 48 int debug; 49 size_t max_failures; 50 useconds_t delay; 51 bool auto_clear_halt; 52 bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *); 53 void (*on_polling_end)(usb_device_t *, bool, void *); 54 bool (*on_error)(usb_device_t *, int, void *); 55 47 56 usb_device_t *dev; 48 57 size_t pipe_index; 49 usb_polling_callback_t callback;50 usb_polling_terminted_callback_t terminated_callback;51 58 size_t request_size; 52 59 uint8_t *buffer; … … 54 61 } polling_data_t; 55 62 63 56 64 /** Polling fibril. 57 65 * … … 66 74 usb_pipe_t *pipe 67 75 = polling_data->dev->pipes[polling_data->pipe_index].pipe; 76 77 if (polling_data->debug > 0) { 78 usb_endpoint_mapping_t *mapping 79 = &polling_data->dev->pipes[polling_data->pipe_index]; 80 usb_log_debug("Poll0x%x: started polling of `%s' - " \ 81 "interface %d (%s,%d,%d), %zuB/%zu.\n", 82 polling_data, 83 polling_data->dev->ddf_dev->name, 84 (int) mapping->interface->interface_number, 85 usb_str_class(mapping->interface->interface_class), 86 (int) mapping->interface->interface_subclass, 87 (int) mapping->interface->interface_protocol, 88 polling_data->request_size, pipe->max_packet_size); 89 } 68 90 69 91 size_t failed_attempts = 0; 70 while (failed_attempts < MAX_FAILED_ATTEMPTS) {92 while (failed_attempts <= polling_data->max_failures) { 71 93 int rc; 72 73 rc = usb_pipe_start_session(pipe);74 if (rc != EOK) {75 failed_attempts++;76 continue;77 }78 94 79 95 size_t actual_size; … … 81 97 polling_data->request_size, &actual_size); 82 98 83 /* Quit the session regardless of errors. */ 84 usb_pipe_end_session(pipe); 99 if (polling_data->debug > 1) { 100 if (rc == EOK) { 101 usb_log_debug( 102 "Poll0x%x: received: '%s' (%zuB).\n", 103 polling_data, 104 usb_debug_str_buffer(polling_data->buffer, 105 actual_size, 16), 106 actual_size); 107 } else { 108 usb_log_debug( 109 "Poll0x%x: polling failed: %s.\n", 110 polling_data, str_error(rc)); 111 } 112 } 113 114 /* If the pipe stalled, we can try to reset the stall. */ 115 if ((rc == ESTALL) && (polling_data->auto_clear_halt)) { 116 /* 117 * We ignore error here as this is usually a futile 118 * attempt anyway. 119 */ 120 usb_request_clear_endpoint_halt( 121 &polling_data->dev->ctrl_pipe, 122 pipe->endpoint_no); 123 } 85 124 86 125 if (rc != EOK) { 126 if (polling_data->on_error != NULL) { 127 bool cont = polling_data->on_error( 128 polling_data->dev, rc, 129 polling_data->custom_arg); 130 if (!cont) { 131 failed_attempts 132 = polling_data->max_failures; 133 } 134 } 87 135 failed_attempts++; 88 136 continue; … … 90 138 91 139 /* We have the data, execute the callback now. */ 92 bool carry_on = polling_data-> callback(polling_data->dev,140 bool carry_on = polling_data->on_data(polling_data->dev, 93 141 polling_data->buffer, actual_size, 94 142 polling_data->custom_arg); … … 101 149 /* Reset as something might be only a temporary problem. */ 102 150 failed_attempts = 0; 103 } 104 105 if (failed_attempts > 0) { 106 usb_log_error( 107 "Polling of device `%s' terminated: recurring failures.\n", 108 polling_data->dev->ddf_dev->name); 109 } 110 111 if (polling_data->terminated_callback != NULL) { 112 polling_data->terminated_callback(polling_data->dev, 151 152 /* Take a rest before next request. */ 153 async_usleep(polling_data->delay); 154 } 155 156 if (polling_data->on_polling_end != NULL) { 157 polling_data->on_polling_end(polling_data->dev, 113 158 failed_attempts > 0, polling_data->custom_arg); 159 } 160 161 if (polling_data->debug > 0) { 162 if (failed_attempts > 0) { 163 usb_log_error( 164 "Polling of device `%s' terminated: %s.\n", 165 polling_data->dev->ddf_dev->name, 166 "recurring failures"); 167 } else { 168 usb_log_debug( 169 "Polling of device `%s' terminated by user.\n", 170 polling_data->dev->ddf_dev->name 171 ); 172 } 114 173 } 115 174 … … 154 213 } 155 214 215 usb_device_auto_polling_t *auto_polling 216 = malloc(sizeof(usb_device_auto_polling_t)); 217 if (auto_polling == NULL) { 218 return ENOMEM; 219 } 220 221 auto_polling->debug = 1; 222 auto_polling->auto_clear_halt = true; 223 auto_polling->delay = 0; 224 auto_polling->max_failures = MAX_FAILED_ATTEMPTS; 225 auto_polling->on_data = callback; 226 auto_polling->on_polling_end = terminated_callback; 227 auto_polling->on_error = NULL; 228 229 int rc = usb_device_auto_polling(dev, pipe_index, auto_polling, 230 request_size, arg); 231 232 free(auto_polling); 233 234 return rc; 235 } 236 237 /** Start automatic device polling over interrupt in pipe. 238 * 239 * The polling settings is copied thus it is okay to destroy the structure 240 * after this function returns. 241 * 242 * @warning There is no guarantee when the request to the device 243 * will be sent for the first time (it is possible that this 244 * first request would be executed prior to return from this function). 245 * 246 * @param dev Device to be periodically polled. 247 * @param pipe_index Index of the endpoint pipe used for polling. 248 * @param polling Polling settings. 249 * @param request_size How many bytes to ask for in each request. 250 * @param arg Custom argument (passed as is to the callbacks). 251 * @return Error code. 252 * @retval EOK New fibril polling the device was already started. 253 */ 254 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index, 255 usb_device_auto_polling_t *polling, 256 size_t request_size, void *arg) 257 { 258 if (dev == NULL) { 259 return EBADMEM; 260 } 261 if (pipe_index >= dev->pipes_count) { 262 return EINVAL; 263 } 264 if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT) 265 || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) { 266 return EINVAL; 267 } 268 if ((polling == NULL) || (polling->on_data == NULL)) { 269 return EBADMEM; 270 } 271 156 272 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); 157 273 if (polling_data == NULL) { … … 159 275 } 160 276 161 /* Allocate now to prevent immediate failure in the polling fibril. */162 polling_data->buffer = malloc( request_size);277 /* Fill-in the data. */ 278 polling_data->buffer = malloc(sizeof(request_size)); 163 279 if (polling_data->buffer == NULL) { 164 280 free(polling_data); 165 281 return ENOMEM; 166 282 } 283 polling_data->request_size = request_size; 167 284 polling_data->dev = dev; 168 285 polling_data->pipe_index = pipe_index; 169 polling_data->callback = callback;170 polling_data->terminated_callback = terminated_callback;171 polling_data->request_size = request_size;172 286 polling_data->custom_arg = arg; 287 288 polling_data->debug = polling->debug; 289 polling_data->max_failures = polling->max_failures; 290 if (polling->delay >= 0) { 291 polling_data->delay = (useconds_t) polling->delay; 292 } else { 293 polling_data->delay = (useconds_t) dev->pipes[pipe_index] 294 .descriptor->poll_interval; 295 } 296 polling_data->auto_clear_halt = polling->auto_clear_halt; 297 298 polling_data->on_data = polling->on_data; 299 polling_data->on_polling_end = polling->on_polling_end; 300 polling_data->on_error = polling->on_error; 173 301 174 302 fid_t fibril = fibril_create(polling_fibril, polling_data); … … 176 304 free(polling_data->buffer); 177 305 free(polling_data); 178 /* FIXME: better error code. */179 306 return ENOMEM; 180 307 } 181 308 fibril_add_ready(fibril); 182 309 183 /* The allocated buffer etc. will be freed by the fibril. */310 /* Fibril launched. That fibril will free the allocated data. */ 184 311 185 312 return EOK; -
uspace/lib/usb/src/hidparser.c
ref354b6 re50cd7f 877 877 878 878 offset = item->offset + (j * item->size); 879 880 879 // FIXME 881 880 if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) { … … 1352 1351 1353 1352 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1354 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1355 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 1356 ret++; 1357 } 1358 usb_hid_report_remove_last_item (field->collection_path); 1353 if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){ 1354 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1355 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) { 1356 ret++; 1357 } 1358 usb_hid_report_remove_last_item (field->collection_path); 1359 } 1359 1360 1360 1361 field_it = field_it->next; … … 1536 1537 1537 1538 /** 1538 * Clones given report item structure and returns the new one1539 *1540 * @param item Report item structure to clone1541 * @return Clonned item1542 */1543 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)1544 {1545 usb_hid_report_item_t *new_report_item;1546 1547 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {1548 return NULL;1549 }1550 memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));1551 link_initialize(&(new_report_item->link));1552 1553 return new_report_item;1554 }1555 1556 1557 /**1558 1539 * 1559 1540 * … … 1604 1585 } 1605 1586 1587 1588 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item) 1589 { 1590 usb_hid_report_item_t *new_report_item; 1591 1592 if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) { 1593 return NULL; 1594 } 1595 memcpy(new_report_item,item, sizeof(usb_hid_report_item_t)); 1596 link_initialize(&(new_report_item->link)); 1597 1598 return new_report_item; 1599 } 1600 1601 1602 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 1603 usb_hid_report_field_t *field, 1604 usb_hid_report_path_t *path, int flags, 1605 usb_hid_report_type_t type) 1606 { 1607 usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type); 1608 link_t *field_it; 1609 1610 if(report_des == NULL){ 1611 return NULL; 1612 } 1613 1614 if(field == NULL){ 1615 // vezmu prvni co mathuje podle path!! 1616 field_it = report_des->report_items.next; 1617 } 1618 else { 1619 field_it = field->link.next; 1620 } 1621 1622 while(field_it != &report_des->report_items) { 1623 field = list_get_instance(field_it, usb_hid_report_field_t, link); 1624 1625 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage); 1626 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){ 1627 usb_hid_report_remove_last_item (field->collection_path); 1628 usb_log_debug("....OK\n"); 1629 return field; 1630 } 1631 usb_hid_report_remove_last_item (field->collection_path); 1632 1633 field_it = field_it->next; 1634 } 1635 1636 return NULL; 1637 } 1606 1638 /** 1607 1639 * @} -
uspace/lib/usb/src/hidreport.c
ref354b6 re50cd7f 80 80 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 81 81 dev->descriptors.configuration, d); 82 ++i; 82 83 } 83 84 … … 118 119 uint16_t length = hid_desc->report_desc_info.length; 119 120 size_t actual_size = 0; 120 121 /*122 * Start session for the control transfer.123 */124 int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);125 if (sess_rc != EOK) {126 usb_log_warning("Failed to start a session: %s.\n",127 str_error(sess_rc));128 return sess_rc;129 }130 121 131 122 /* … … 161 152 "%u)\n", actual_size, length); 162 153 return EINVAL; 163 }164 165 /*166 * End session for the control transfer.167 */168 sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);169 if (sess_rc != EOK) {170 usb_log_warning("Failed to end a session: %s.\n",171 str_error(sess_rc));172 free(*report_desc);173 *report_desc = NULL;174 return sess_rc;175 154 } 176 155 -
uspace/lib/usb/src/hidreq.c
ref354b6 re50cd7f 56 56 * @retval EOK if successful. 57 57 * @retval EINVAL if no HID device is given. 58 * @return Other value inherited from one of functions 59 * usb_pipe_start_session(), usb_pipe_end_session(), 60 * usb_control_request_set(). 58 * @return Other value inherited from function usb_control_request_set(). 61 59 */ 62 60 int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no, … … 79 77 */ 80 78 81 int rc, sess_rc; 82 83 sess_rc = usb_pipe_start_session(ctrl_pipe); 84 if (sess_rc != EOK) { 85 usb_log_warning("Failed to start a session: %s.\n", 86 str_error(sess_rc)); 87 return sess_rc; 88 } 79 int rc; 89 80 90 81 uint16_t value = 0; … … 97 88 USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size); 98 89 99 sess_rc = usb_pipe_end_session(ctrl_pipe); 100 101 if (rc != EOK) { 102 usb_log_warning("Error sending output report to the keyboard: " 103 "%s.\n", str_error(rc)); 104 return rc; 105 } 106 107 if (sess_rc != EOK) { 108 usb_log_warning("Error closing session: %s.\n", 109 str_error(sess_rc)); 110 return sess_rc; 90 if (rc != EOK) { 91 usb_log_warning("Error sending output report to the keyboard: " 92 "%s.\n", str_error(rc)); 93 return rc; 111 94 } 112 95 … … 123 106 * @retval EOK if successful. 124 107 * @retval EINVAL if no HID device is given. 125 * @return Other value inherited from one of functions 126 * usb_pipe_start_session(), usb_pipe_end_session(), 127 * usb_control_request_set(). 108 * @return Other value inherited from function usb_control_request_set(). 128 109 */ 129 110 int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no, … … 146 127 */ 147 128 148 int rc, sess_rc; 149 150 sess_rc = usb_pipe_start_session(ctrl_pipe); 151 if (sess_rc != EOK) { 152 usb_log_warning("Failed to start a session: %s.\n", 153 str_error(sess_rc)); 154 return sess_rc; 155 } 129 int rc; 156 130 157 131 usb_log_debug("Sending Set_Protocol request to the device (" … … 162 136 USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0); 163 137 164 sess_rc = usb_pipe_end_session(ctrl_pipe); 165 166 if (rc != EOK) { 167 usb_log_warning("Error sending output report to the keyboard: " 168 "%s.\n", str_error(rc)); 169 return rc; 170 } 171 172 if (sess_rc != EOK) { 173 usb_log_warning("Error closing session: %s.\n", 174 str_error(sess_rc)); 175 return sess_rc; 138 if (rc != EOK) { 139 usb_log_warning("Error sending output report to the keyboard: " 140 "%s.\n", str_error(rc)); 141 return rc; 176 142 } 177 143 … … 189 155 * @retval EOK if successful. 190 156 * @retval EINVAL if no HID device is given. 191 * @return Other value inherited from one of functions 192 * usb_pipe_start_session(), usb_pipe_end_session(), 193 * usb_control_request_set(). 157 * @return Other value inherited from function usb_control_request_set(). 194 158 */ 195 159 int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration) … … 211 175 */ 212 176 213 int rc, sess_rc; 214 215 sess_rc = usb_pipe_start_session(ctrl_pipe); 216 if (sess_rc != EOK) { 217 usb_log_warning("Failed to start a session: %s.\n", 218 str_error(sess_rc)); 219 return sess_rc; 220 } 177 int rc; 221 178 222 179 usb_log_debug("Sending Set_Idle request to the device (" … … 229 186 USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0); 230 187 231 sess_rc = usb_pipe_end_session(ctrl_pipe); 232 233 if (rc != EOK) { 234 usb_log_warning("Error sending output report to the keyboard: " 235 "%s.\n", str_error(rc)); 236 return rc; 237 } 238 239 if (sess_rc != EOK) { 240 usb_log_warning("Error closing session: %s.\n", 241 str_error(sess_rc)); 242 return sess_rc; 188 if (rc != EOK) { 189 usb_log_warning("Error sending output report to the keyboard: " 190 "%s.\n", str_error(rc)); 191 return rc; 243 192 } 244 193 … … 259 208 * @retval EOK if successful. 260 209 * @retval EINVAL if no HID device is given. 261 * @return Other value inherited from one of functions 262 * usb_pipe_start_session(), usb_pipe_end_session(), 263 * usb_control_request_set(). 210 * @return Other value inherited from function usb_control_request_set(). 264 211 */ 265 212 int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, … … 283 230 */ 284 231 285 int rc, sess_rc; 286 287 sess_rc = usb_pipe_start_session(ctrl_pipe); 288 if (sess_rc != EOK) { 289 usb_log_warning("Failed to start a session: %s.\n", 290 str_error(sess_rc)); 291 return sess_rc; 292 } 232 int rc; 293 233 294 234 uint16_t value = 0; … … 302 242 actual_size); 303 243 304 sess_rc = usb_pipe_end_session(ctrl_pipe); 305 306 if (rc != EOK) { 307 usb_log_warning("Error sending output report to the keyboard: " 308 "%s.\n", str_error(rc)); 309 return rc; 310 } 311 312 if (sess_rc != EOK) { 313 usb_log_warning("Error closing session: %s.\n", 314 str_error(sess_rc)); 315 return sess_rc; 244 if (rc != EOK) { 245 usb_log_warning("Error sending output report to the keyboard: " 246 "%s.\n", str_error(rc)); 247 return rc; 316 248 } 317 249 … … 328 260 * @retval EOK if successful. 329 261 * @retval EINVAL if no HID device is given. 330 * @return Other value inherited from one of functions 331 * usb_pipe_start_session(), usb_pipe_end_session(), 332 * usb_control_request_set(). 262 * @return Other value inherited from function usb_control_request_set(). 333 263 */ 334 264 int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, … … 351 281 */ 352 282 353 int rc, sess_rc; 354 355 sess_rc = usb_pipe_start_session(ctrl_pipe); 356 if (sess_rc != EOK) { 357 usb_log_warning("Failed to start a session: %s.\n", 358 str_error(sess_rc)); 359 return sess_rc; 360 } 283 int rc; 361 284 362 285 usb_log_debug("Sending Get_Protocol request to the device (" … … 370 293 USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size); 371 294 372 sess_rc = usb_pipe_end_session(ctrl_pipe); 373 374 if (rc != EOK) { 375 usb_log_warning("Error sending output report to the keyboard: " 376 "%s.\n", str_error(rc)); 377 return rc; 378 } 379 380 if (sess_rc != EOK) { 381 usb_log_warning("Error closing session: %s.\n", 382 str_error(sess_rc)); 383 return sess_rc; 295 if (rc != EOK) { 296 usb_log_warning("Error sending output report to the keyboard: " 297 "%s.\n", str_error(rc)); 298 return rc; 384 299 } 385 300 … … 427 342 */ 428 343 429 int rc, sess_rc; 430 431 sess_rc = usb_pipe_start_session(ctrl_pipe); 432 if (sess_rc != EOK) { 433 usb_log_warning("Failed to start a session: %s.\n", 434 str_error(sess_rc)); 435 return sess_rc; 436 } 344 int rc; 437 345 438 346 usb_log_debug("Sending Get_Idle request to the device (" … … 448 356 &actual_size); 449 357 450 sess_rc = usb_pipe_end_session(ctrl_pipe); 451 452 if (rc != EOK) { 453 usb_log_warning("Error sending output report to the keyboard: " 454 "%s.\n", str_error(rc)); 455 return rc; 456 } 457 458 if (sess_rc != EOK) { 459 usb_log_warning("Error closing session: %s.\n", 460 str_error(sess_rc)); 461 return sess_rc; 358 if (rc != EOK) { 359 usb_log_warning("Error sending output report to the keyboard: " 360 "%s.\n", str_error(rc)); 361 return rc; 462 362 } 463 363 -
uspace/lib/usb/src/host/batch.c
ref354b6 re50cd7f 39 39 #include <usb/host/batch.h> 40 40 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 41 44 void usb_transfer_batch_init( 42 45 usb_transfer_batch_t *instance, 43 usb_target_t target, 44 usb_transfer_type_t transfer_type, 45 usb_speed_t speed, 46 size_t max_packet_size, 46 endpoint_t *ep, 47 47 char *buffer, 48 char * transport_buffer,48 char *data_buffer, 49 49 size_t buffer_size, 50 50 char *setup_buffer, … … 54 54 void *arg, 55 55 ddf_fun_t *fun, 56 endpoint_t *ep,57 void *private_data56 void *private_data, 57 void (*private_data_dtor)(void *p_data) 58 58 ) 59 59 { 60 60 assert(instance); 61 61 link_initialize(&instance->link); 62 instance->target = target; 63 instance->transfer_type = transfer_type; 64 instance->speed = speed; 65 instance->direction = USB_DIRECTION_BOTH; 62 instance->ep = ep; 66 63 instance->callback_in = func_in; 67 64 instance->callback_out = func_out; 68 65 instance->arg = arg; 69 66 instance->buffer = buffer; 70 instance-> transport_buffer = transport_buffer;67 instance->data_buffer = data_buffer; 71 68 instance->buffer_size = buffer_size; 72 69 instance->setup_buffer = setup_buffer; 73 70 instance->setup_size = setup_size; 74 instance->max_packet_size = max_packet_size;75 71 instance->fun = fun; 76 72 instance->private_data = private_data; 73 instance->private_data_dtor = private_data_dtor; 77 74 instance->transfered_size = 0; 78 75 instance->next_step = NULL; 79 76 instance->error = EOK; 80 instance->ep = ep; 77 endpoint_use(instance->ep); 78 } 79 /*----------------------------------------------------------------------------*/ 80 /** Helper function, calls callback and correctly destroys batch structure. 81 * 82 * @param[in] instance Batch structure to use. 83 */ 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); 81 100 } 82 101 /*----------------------------------------------------------------------------*/ … … 86 105 * 87 106 */ 88 void usb_transfer_batch_finish(usb_transfer_batch_t *instance , int error)107 void usb_transfer_batch_finish(usb_transfer_batch_t *instance) 89 108 { 90 109 assert(instance); 91 instance->error = error; 110 assert(instance->ep); 111 endpoint_release(instance->ep); 92 112 instance->next_step(instance); 93 113 } … … 103 123 assert(instance); 104 124 assert(instance->callback_in); 125 assert(instance->ep); 105 126 106 127 /* We are data in, we need data */ 107 memcpy(instance->buffer, instance->transport_buffer, 108 instance->buffer_size); 128 memcpy(instance->buffer, instance->data_buffer, instance->buffer_size); 109 129 110 130 usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n", 111 instance, 112 instance->target.address, instance->target.endpoint, 113 usb_str_speed(instance->speed), 114 usb_str_transfer_type_short(instance->transfer_type), 115 instance->transfered_size, 116 str_error(instance->error), instance->error); 131 instance, instance->ep->address, instance->ep->endpoint, 132 usb_str_speed(instance->ep->speed), 133 usb_str_transfer_type_short(instance->ep->transfer_type), 134 instance->transfered_size, str_error(instance->error), instance->error); 117 135 118 136 instance->callback_in(instance->fun, instance->error, … … 130 148 131 149 usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n", 132 instance, 133 instance->target.address, instance->target.endpoint, 134 usb_str_speed(instance->speed), 135 usb_str_transfer_type_short(instance->transfer_type), 150 instance, instance->ep->address, instance->ep->endpoint, 151 usb_str_speed(instance->ep->speed), 152 usb_str_transfer_type_short(instance->ep->transfer_type), 136 153 str_error(instance->error), instance->error); 137 154 … … 139 156 instance->error, instance->arg); 140 157 } 158 /*----------------------------------------------------------------------------*/ 159 /** Correctly dispose all used data structures. 160 * 161 * @param[in] instance Batch structure to use. 162 */ 163 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance) 164 { 165 assert(instance); 166 usb_log_debug("Batch(%p) disposing.\n", instance); 167 if (instance->private_data) { 168 assert(instance->private_data_dtor); 169 instance->private_data_dtor(instance->private_data); 170 } 171 free(instance); 172 } 141 173 /** 142 174 * @} -
uspace/lib/usb/src/host/device_keeper.c
ref354b6 re50cd7f 48 48 { 49 49 assert(instance); 50 fibril_mutex_initialize(&instance->guard);51 fibril_condvar_initialize(&instance->change);52 instance->last_address = 0;53 50 unsigned i = 0; 54 51 for (; i < USB_ADDRESS_COUNT; ++i) { 55 52 instance->devices[i].occupied = false; 56 instance->devices[i].control_used = 0;57 53 instance->devices[i].handle = 0; 58 list_initialize(&instance->devices[i].endpoints);54 instance->devices[i].speed = USB_SPEED_MAX; 59 55 } 60 } 61 /*----------------------------------------------------------------------------*/ 62 void usb_device_keeper_add_ep( 63 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 64 { 65 assert(instance); 66 fibril_mutex_lock(&instance->guard); 67 assert(instance->devices[address].occupied); 68 list_append(&ep->same_device_eps, &instance->devices[address].endpoints); 69 fibril_mutex_unlock(&instance->guard); 70 } 71 /*----------------------------------------------------------------------------*/ 72 /** Attempt to obtain address 0, blocks. 73 * 74 * @param[in] instance Device keeper structure to use. 75 * @param[in] speed Speed of the device requesting default address. 76 */ 77 void usb_device_keeper_reserve_default_address( 78 usb_device_keeper_t *instance, usb_speed_t speed) 79 { 80 assert(instance); 81 fibril_mutex_lock(&instance->guard); 82 while (instance->devices[USB_ADDRESS_DEFAULT].occupied) { 83 fibril_condvar_wait(&instance->change, &instance->guard); 84 } 85 instance->devices[USB_ADDRESS_DEFAULT].occupied = true; 86 instance->devices[USB_ADDRESS_DEFAULT].speed = speed; 87 fibril_mutex_unlock(&instance->guard); 88 } 89 /*----------------------------------------------------------------------------*/ 90 /** Attempt to obtain address 0, blocks. 91 * 92 * @param[in] instance Device keeper structure to use. 93 * @param[in] speed Speed of the device requesting default address. 94 */ 95 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance) 96 { 97 assert(instance); 98 fibril_mutex_lock(&instance->guard); 99 instance->devices[USB_ADDRESS_DEFAULT].occupied = false; 100 fibril_mutex_unlock(&instance->guard); 101 fibril_condvar_signal(&instance->change); 102 } 103 /*----------------------------------------------------------------------------*/ 104 /** Check setup packet data for signs of toggle reset. 105 * 106 * @param[in] instance Device keeper structure to use. 107 * @param[in] target Device to receive setup packet. 108 * @param[in] data Setup packet data. 109 * 110 * Really ugly one. 111 */ 112 void usb_device_keeper_reset_if_need( 113 usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data) 114 { 115 assert(instance); 116 fibril_mutex_lock(&instance->guard); 117 if (target.endpoint > 15 || target.endpoint < 0 118 || target.address >= USB_ADDRESS_COUNT || target.address < 0 119 || !instance->devices[target.address].occupied) { 120 fibril_mutex_unlock(&instance->guard); 121 usb_log_error("Invalid data when checking for toggle reset.\n"); 122 return; 123 } 124 125 switch (data[1]) 126 { 127 case 0x01: /*clear feature*/ 128 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 129 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 130 link_t *current = 131 instance->devices[target.address].endpoints.next; 132 while (current != 133 &instance->devices[target.address].endpoints) 134 { 135 /* endpoint number is < 16, thus first byte is enough */ 136 endpoint_toggle_reset_filtered( 137 current, data[4]); 138 current = current->next; 139 } 140 } 141 break; 142 143 case 0x9: /* set configuration */ 144 case 0x11: /* set interface */ 145 /* target must be device */ 146 if ((data[0] & 0xf) == 0) { 147 link_t *current = 148 instance->devices[target.address].endpoints.next; 149 while (current != 150 &instance->devices[target.address].endpoints) 151 { 152 endpoint_toggle_reset(current); 153 current = current->next; 154 } 155 } 156 break; 157 } 158 fibril_mutex_unlock(&instance->guard); 56 // TODO: is this hack enough? 57 // (it is needed to allow smooth registration at default address) 58 instance->devices[0].occupied = true; 59 instance->last_address = 0; 60 fibril_mutex_initialize(&instance->guard); 159 61 } 160 62 /*----------------------------------------------------------------------------*/ … … 184 86 assert(new_address != USB_ADDRESS_DEFAULT); 185 87 assert(instance->devices[new_address].occupied == false); 88 186 89 instance->devices[new_address].occupied = true; 187 90 instance->devices[new_address].speed = speed; 188 91 instance->last_address = new_address; 92 189 93 fibril_mutex_unlock(&instance->guard); 190 94 return new_address; … … 202 106 assert(instance); 203 107 fibril_mutex_lock(&instance->guard); 108 204 109 assert(address > 0); 205 110 assert(address <= USB11_ADDRESS_MAX); 206 111 assert(instance->devices[address].occupied); 112 207 113 instance->devices[address].handle = handle; 208 114 fibril_mutex_unlock(&instance->guard); … … 223 129 fibril_mutex_lock(&instance->guard); 224 130 assert(instance->devices[address].occupied); 131 225 132 instance->devices[address].occupied = false; 226 133 fibril_mutex_unlock(&instance->guard); … … 241 148 while (address <= USB11_ADDRESS_MAX) { 242 149 if (instance->devices[address].handle == handle) { 150 assert(instance->devices[address].occupied); 243 151 fibril_mutex_unlock(&instance->guard); 244 152 return address; … … 262 170 assert(address >= 0); 263 171 assert(address <= USB11_ADDRESS_MAX); 172 264 173 return instance->devices[address].speed; 265 }266 /*----------------------------------------------------------------------------*/267 void usb_device_keeper_use_control(268 usb_device_keeper_t *instance, usb_target_t target)269 {270 assert(instance);271 const uint16_t ep = 1 << target.endpoint;272 fibril_mutex_lock(&instance->guard);273 while (instance->devices[target.address].control_used & ep) {274 fibril_condvar_wait(&instance->change, &instance->guard);275 }276 instance->devices[target.address].control_used |= ep;277 fibril_mutex_unlock(&instance->guard);278 }279 /*----------------------------------------------------------------------------*/280 void usb_device_keeper_release_control(281 usb_device_keeper_t *instance, usb_target_t target)282 {283 assert(instance);284 const uint16_t ep = 1 << target.endpoint;285 fibril_mutex_lock(&instance->guard);286 assert((instance->devices[target.address].control_used & ep) != 0);287 instance->devices[target.address].control_used &= ~ep;288 fibril_mutex_unlock(&instance->guard);289 fibril_condvar_signal(&instance->change);290 174 } 291 175 /** -
uspace/lib/usb/src/host/endpoint.c
ref354b6 re50cd7f 34 34 */ 35 35 36 #include <assert.h> 36 37 #include <errno.h> 37 38 #include <usb/host/endpoint.h> … … 49 50 instance->max_packet_size = max_packet_size; 50 51 instance->toggle = 0; 51 link_initialize(&instance->same_device_eps); 52 instance->active = false; 53 fibril_mutex_initialize(&instance->guard); 54 fibril_condvar_initialize(&instance->avail); 55 endpoint_clear_hc_data(instance); 52 56 return EOK; 53 57 } … … 56 60 { 57 61 assert(instance); 58 list_remove(&instance->same_device_eps);62 assert(!instance->active); 59 63 free(instance); 64 } 65 /*----------------------------------------------------------------------------*/ 66 void endpoint_set_hc_data(endpoint_t *instance, 67 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 68 { 69 assert(instance); 70 instance->hc_data.data = data; 71 instance->hc_data.toggle_get = toggle_get; 72 instance->hc_data.toggle_set = toggle_set; 73 } 74 /*----------------------------------------------------------------------------*/ 75 void endpoint_clear_hc_data(endpoint_t *instance) 76 { 77 assert(instance); 78 instance->hc_data.data = NULL; 79 instance->hc_data.toggle_get = NULL; 80 instance->hc_data.toggle_set = NULL; 81 } 82 /*----------------------------------------------------------------------------*/ 83 void endpoint_use(endpoint_t *instance) 84 { 85 assert(instance); 86 fibril_mutex_lock(&instance->guard); 87 while (instance->active) 88 fibril_condvar_wait(&instance->avail, &instance->guard); 89 instance->active = true; 90 fibril_mutex_unlock(&instance->guard); 91 } 92 /*----------------------------------------------------------------------------*/ 93 void endpoint_release(endpoint_t *instance) 94 { 95 assert(instance); 96 fibril_mutex_lock(&instance->guard); 97 instance->active = false; 98 fibril_mutex_unlock(&instance->guard); 99 fibril_condvar_signal(&instance->avail); 60 100 } 61 101 /*----------------------------------------------------------------------------*/ … … 63 103 { 64 104 assert(instance); 105 if (instance->hc_data.toggle_get) 106 instance->toggle = 107 instance->hc_data.toggle_get(instance->hc_data.data); 65 108 return (int)instance->toggle; 66 109 } … … 70 113 assert(instance); 71 114 assert(toggle == 0 || toggle == 1); 115 if (instance->hc_data.toggle_set) 116 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 72 117 instance->toggle = toggle; 73 118 } 74 119 /*----------------------------------------------------------------------------*/ 75 void endpoint_toggle_reset (link_t *ep)120 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target) 76 121 { 77 endpoint_t *instance =78 list_get_instance(ep, endpoint_t, same_device_eps);79 122 assert(instance); 80 instance->toggle = 0; 81 } 82 /*----------------------------------------------------------------------------*/ 83 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn) 84 { 85 endpoint_t *instance = 86 list_get_instance(ep, endpoint_t, same_device_eps); 87 assert(instance); 88 if (instance->endpoint == epn) 89 instance->toggle = 0; 123 if (instance->address == target.address && 124 (instance->endpoint == target.endpoint || target.endpoint == 0)) 125 endpoint_toggle_set(instance, 0); 90 126 } 91 127 /** -
uspace/lib/usb/src/host/usb_endpoint_manager.c
ref354b6 re50cd7f 31 31 #include <errno.h> 32 32 33 #include <usb/debug.h> 33 34 #include <usb/host/usb_endpoint_manager.h> 34 35 … … 80 81 endpoint_destroy(node->ep); 81 82 free(node); 83 } 84 /*----------------------------------------------------------------------------*/ 85 static void node_toggle_reset_filtered(link_t *item, void *arg) 86 { 87 assert(item); 88 node_t *node = hash_table_get_instance(item, node_t, link); 89 usb_target_t *target = arg; 90 endpoint_toggle_reset_filtered(node->ep, *target); 82 91 } 83 92 /*----------------------------------------------------------------------------*/ … … 202 211 203 212 node_t *node = hash_table_get_instance(item, node_t, link); 213 if (node->ep->active) 214 return EBUSY; 215 204 216 instance->free_bw += node->bw; 205 217 hash_table_remove(&instance->ep_table, key, MAX_KEYS); … … 230 242 return node->ep; 231 243 } 244 /*----------------------------------------------------------------------------*/ 245 /** Check setup packet data for signs of toggle reset. 246 * 247 * @param[in] instance Device keeper structure to use. 248 * @param[in] target Device to receive setup packet. 249 * @param[in] data Setup packet data. 250 * 251 * Really ugly one. 252 */ 253 void usb_endpoint_manager_reset_if_need( 254 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data) 255 { 256 assert(instance); 257 if (target.endpoint > 15 || target.endpoint < 0 258 || target.address >= USB11_ADDRESS_MAX || target.address < 0) { 259 usb_log_error("Invalid data when checking for toggle reset.\n"); 260 return; 261 } 262 263 switch (data[1]) 264 { 265 case 0x01: /*clear feature*/ 266 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 267 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 268 /* endpoint number is < 16, thus first byte is enough */ 269 usb_target_t reset_target = 270 { .address = target.address, data[4] }; 271 fibril_mutex_lock(&instance->guard); 272 hash_table_apply(&instance->ep_table, 273 node_toggle_reset_filtered, &reset_target); 274 fibril_mutex_unlock(&instance->guard); 275 } 276 break; 277 278 case 0x9: /* set configuration */ 279 case 0x11: /* set interface */ 280 /* target must be device */ 281 if ((data[0] & 0xf) == 0) { 282 usb_target_t reset_target = 283 { .address = target.address, 0 }; 284 fibril_mutex_lock(&instance->guard); 285 hash_table_apply(&instance->ep_table, 286 node_toggle_reset_filtered, &reset_target); 287 fibril_mutex_unlock(&instance->guard); 288 } 289 break; 290 } 291 } -
uspace/lib/usb/src/hub.c
ref354b6 re50cd7f 40 40 #include <errno.h> 41 41 #include <assert.h> 42 #include <usb/debug.h> 43 44 /** How much time to wait between attempts to register endpoint 0:0. 45 * The value is based on typical value for port reset + some overhead. 46 */ 47 #define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2)) 42 48 43 49 /** Check that HC connection is alright. … … 53 59 } while (false) 54 60 55 56 /** Tell host controller to reserve default address.57 *58 * @param connection Opened connection to host controller.59 * @param speed Speed of the device that will respond on the default address.60 * @return Error code.61 */62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,63 usb_speed_t speed)64 {65 CHECK_CONNECTION(connection);66 67 return async_req_2_0(connection->hc_phone,68 DEV_IFACE_ID(USBHC_DEV_IFACE),69 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);70 }71 72 /** Tell host controller to release default address.73 *74 * @param connection Opened connection to host controller.75 * @return Error code.76 */77 int usb_hc_release_default_address(usb_hc_connection_t *connection)78 {79 CHECK_CONNECTION(connection);80 81 return async_req_1_0(connection->hc_phone,82 DEV_IFACE_ID(USBHC_DEV_IFACE),83 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);84 }85 86 61 /** Ask host controller for free address assignment. 87 62 * … … 178 153 * error codes than those listed as return codes by this function itself). 179 154 * 155 * The @p connection representing connection with host controller does not 156 * need to be started. 157 * This function duplicates the connection to allow simultaneous calls of 158 * this function (i.e. from different fibrils). 159 * 180 160 * @param[in] parent Parent device (i.e. the hub device). 181 * @param[in] connection Opened connection to host controller.161 * @param[in] connection Connection to host controller. 182 162 * @param[in] dev_speed New device speed. 183 163 * @param[in] enable_port Function for enabling signaling through the port the … … 206 186 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 207 187 { 208 CHECK_CONNECTION(connection); 188 assert(connection != NULL); 189 // FIXME: this is awful, we are accessing directly the structure. 190 usb_hc_connection_t hc_conn = { 191 .hc_handle = connection->hc_handle, 192 .hc_phone = -1 193 }; 194 195 int rc; 196 197 rc = usb_hc_connection_open(&hc_conn); 198 if (rc != EOK) { 199 return rc; 200 } 201 209 202 210 203 /* 211 204 * Request new address. 212 205 */ 213 usb_address_t dev_addr = usb_hc_request_address( connection, dev_speed);206 usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed); 214 207 if (dev_addr < 0) { 208 usb_hc_connection_close(&hc_conn); 215 209 return EADDRNOTAVAIL; 216 210 } 217 211 218 int rc; 219 220 /* 221 * Reserve the default address. 222 */ 223 rc = usb_hc_reserve_default_address(connection, dev_speed); 224 if (rc != EOK) { 225 rc = EBUSY; 226 goto leave_release_free_address; 227 } 228 229 /* 230 * Enable the port (i.e. allow signaling through this port). 231 */ 232 rc = enable_port(port_no, arg); 233 if (rc != EOK) { 234 goto leave_release_default_address; 235 } 236 237 /* 238 * Change the address from default to the free one. 239 * We need to create a new control pipe for that. 212 /* 213 * We will not register control pipe on default address. 214 * The registration might fail. That means that someone else already 215 * registered that endpoint. We will simply wait and try again. 216 * (Someone else already wants to add a new device.) 240 217 */ 241 218 usb_device_connection_t dev_conn; 242 219 rc = usb_device_connection_initialize_on_default_address(&dev_conn, 243 connection);220 &hc_conn); 244 221 if (rc != EOK) { 245 222 rc = ENOTCONN; 246 goto leave_release_ default_address;223 goto leave_release_free_address; 247 224 } 248 225 … … 252 229 if (rc != EOK) { 253 230 rc = ENOTCONN; 231 goto leave_release_free_address; 232 } 233 234 do { 235 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0, 236 &hc_conn); 237 if (rc != EOK) { 238 /* Do not overheat the CPU ;-). */ 239 async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC); 240 } 241 } while (rc != EOK); 242 243 /* 244 * Endpoint is registered. We can enable the port and change 245 * device address. 246 */ 247 rc = enable_port(port_no, arg); 248 if (rc != EOK) { 254 249 goto leave_release_default_address; 255 250 } 256 251 257 /* Before sending any traffic, we need to register this 258 * endpoint. 259 */ 260 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 261 if (rc != EOK) { 262 rc = EREFUSED; 252 rc = usb_pipe_probe_default_control(&ctrl_pipe); 253 if (rc != EOK) { 254 rc = ESTALL; 263 255 goto leave_release_default_address; 264 256 } 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 266 if (rc != EOK) { 267 rc = ENOTCONN; 257 258 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 259 if (rc != EOK) { 260 rc = ESTALL; 268 261 goto leave_release_default_address; 269 262 } 270 263 271 rc = usb_pipe_start_session(&ctrl_pipe); 272 if (rc != EOK) { 273 rc = ENOTCONN; 274 goto leave_unregister_endpoint; 275 } 276 277 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 278 if (rc != EOK) { 279 rc = ESTALL; 280 goto leave_stop_session; 281 } 282 283 usb_pipe_end_session(&ctrl_pipe); 284 285 /* 286 * Register the control endpoint for the new device. 287 */ 288 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 289 if (rc != EOK) { 290 rc = EREFUSED; 291 goto leave_unregister_endpoint; 292 } 293 294 /* 295 * Release the original endpoint. 296 */ 297 unregister_control_endpoint_on_default_address(connection); 298 299 /* 300 * Once the address is changed, we can return the default address. 301 */ 302 usb_hc_release_default_address(connection); 303 264 /* 265 * Address changed. We can release the original endpoint, thus 266 * allowing other to access the default address. 267 */ 268 unregister_control_endpoint_on_default_address(&hc_conn); 269 270 /* 271 * Time to register the new endpoint. 272 */ 273 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 274 if (rc != EOK) { 275 goto leave_release_free_address; 276 } 304 277 305 278 /* … … 316 289 } 317 290 318 319 320 291 /* 321 292 * And now inform the host controller about the handle. … … 325 296 .handle = child_handle 326 297 }; 327 rc = usb_hc_register_device( connection, &new_device);298 rc = usb_hc_register_device(&hc_conn, &new_device); 328 299 if (rc != EOK) { 329 300 rc = EDESTADDRREQ; … … 349 320 * Completely ignoring errors here. 350 321 */ 351 352 leave_stop_session:353 usb_pipe_end_session(&ctrl_pipe);354 355 leave_unregister_endpoint:356 usb_pipe_unregister(&ctrl_pipe, connection);357 358 322 leave_release_default_address: 359 usb_ hc_release_default_address(connection);323 usb_pipe_unregister(&ctrl_pipe, &hc_conn); 360 324 361 325 leave_release_free_address: 362 usb_hc_unregister_device(connection, dev_addr); 326 usb_hc_unregister_device(&hc_conn, dev_addr); 327 328 usb_hc_connection_close(&hc_conn); 363 329 364 330 return rc; -
uspace/lib/usb/src/pipes.c
ref354b6 re50cd7f 41 41 #include <errno.h> 42 42 #include <assert.h> 43 #include "pipepriv.h" 43 44 44 45 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */ … … 241 242 * necessary. 242 243 * 244 * @deprecated 245 * Obsoleted with introduction of usb_pipe_start_long_transfer 246 * 243 247 * @param pipe Endpoint pipe to start the session on. 244 248 * @return Error code. … … 246 250 int usb_pipe_start_session(usb_pipe_t *pipe) 247 251 { 248 assert(pipe); 249 250 if (usb_pipe_is_session_started(pipe)) { 251 return EBUSY; 252 } 253 254 int phone = devman_device_connect(pipe->wire->hc_handle, 0); 255 if (phone < 0) { 256 return phone; 257 } 258 259 pipe->hc_phone = phone; 260 252 usb_log_warning("usb_pipe_start_session() was deprecated.\n"); 261 253 return EOK; 262 254 } … … 265 257 /** Ends a session on the endpoint pipe. 266 258 * 259 * @deprecated 260 * Obsoleted with introduction of usb_pipe_end_long_transfer 261 * 267 262 * @see usb_pipe_start_session 268 263 * … … 272 267 int usb_pipe_end_session(usb_pipe_t *pipe) 273 268 { 274 assert(pipe); 275 276 if (!usb_pipe_is_session_started(pipe)) { 277 return ENOENT; 278 } 279 280 int rc = async_hangup(pipe->hc_phone); 281 if (rc != EOK) { 282 return rc; 283 } 284 285 pipe->hc_phone = -1; 286 269 usb_log_warning("usb_pipe_end_session() was deprecated.\n"); 287 270 return EOK; 288 271 } … … 298 281 bool usb_pipe_is_session_started(usb_pipe_t *pipe) 299 282 { 300 return (pipe->hc_phone >= 0); 283 pipe_acquire(pipe); 284 bool started = pipe->refcount > 0; 285 pipe_release(pipe); 286 return started; 287 } 288 289 /** Prepare pipe for a long transfer. 290 * 291 * By a long transfer is mean transfer consisting of several 292 * requests to the HC. 293 * Calling such function is optional and it has positive effect of 294 * improved performance because IPC session is initiated only once. 295 * 296 * @param pipe Pipe over which the transfer will happen. 297 * @return Error code. 298 */ 299 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 300 { 301 return pipe_add_ref(pipe); 302 } 303 304 /** Terminate a long transfer on a pipe. 305 * 306 * @see usb_pipe_start_long_transfer 307 * 308 * @param pipe Pipe where to end the long transfer. 309 */ 310 void usb_pipe_end_long_transfer(usb_pipe_t *pipe) 311 { 312 pipe_drop_ref(pipe); 301 313 } 302 314 -
uspace/lib/usb/src/pipesinit.c
ref354b6 re50cd7f 356 356 assert(connection); 357 357 358 fibril_mutex_initialize(&pipe->guard); 358 359 pipe->wire = connection; 359 360 pipe->hc_phone = -1; 361 fibril_mutex_initialize(&pipe->hc_phone_mutex); 360 362 pipe->endpoint_no = endpoint_no; 361 363 pipe->transfer_type = transfer_type; 362 364 pipe->max_packet_size = max_packet_size; 363 365 pipe->direction = direction; 366 pipe->refcount = 0; 367 pipe->auto_reset_halt = false; 364 368 365 369 return EOK; … … 382 386 0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, 383 387 USB_DIRECTION_BOTH); 388 389 pipe->auto_reset_halt = true; 384 390 385 391 return rc; … … 413 419 int rc; 414 420 415 TRY_LOOP(failed_attempts) { 416 rc = usb_pipe_start_session(pipe); 417 if (rc == EOK) { 418 break; 419 } 420 } 421 rc = usb_pipe_start_long_transfer(pipe); 421 422 if (rc != EOK) { 422 423 return rc; … … 439 440 } 440 441 } 441 usb_pipe_end_ session(pipe);442 usb_pipe_end_long_transfer(pipe); 442 443 if (rc != EOK) { 443 444 return rc; … … 461 462 usb_hc_connection_t *hc_connection) 462 463 { 464 return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1, 465 interval, hc_connection); 466 } 467 468 /** Register endpoint with a speed at the host controller. 469 * 470 * You will rarely need to use this function because it is needed only 471 * if the registered endpoint is of address 0 and there is no other way 472 * to tell speed of the device at address 0. 473 * 474 * @param pipe Pipe to be registered. 475 * @param speed Speed of the device 476 * (invalid speed means use previously specified one). 477 * @param interval Polling interval. 478 * @param hc_connection Connection to the host controller (must be opened). 479 * @return Error code. 480 */ 481 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed, 482 unsigned int interval, 483 usb_hc_connection_t *hc_connection) 484 { 463 485 assert(pipe); 464 486 assert(hc_connection); … … 468 490 } 469 491 470 #define _PACK(high, low) ((high) * 256 + (low)) 471 472 return async_req_5_0(hc_connection->hc_phone, 492 #define _PACK2(high, low) (((high) << 16) + (low)) 493 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) 494 495 return async_req_4_0(hc_connection->hc_phone, 473 496 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT, 474 _PACK(pipe->wire->address, pipe->endpoint_no), 475 _PACK(pipe->transfer_type, pipe->direction), 476 pipe->max_packet_size, interval); 477 478 #undef _PACK 497 _PACK2(pipe->wire->address, pipe->endpoint_no), 498 _PACK3(speed, pipe->transfer_type, pipe->direction), 499 _PACK2(pipe->max_packet_size, interval)); 500 501 #undef _PACK2 502 #undef _PACK3 479 503 } 480 504 -
uspace/lib/usb/src/pipesio.c
ref354b6 re50cd7f 49 49 #include <assert.h> 50 50 #include <usbhc_iface.h> 51 #include <usb/request.h> 52 #include "pipepriv.h" 51 53 52 54 /** Request an in transfer, no checking of input parameters. … … 78 80 } 79 81 82 /* Ensure serialization over the phone. */ 83 pipe_start_transaction(pipe); 84 80 85 /* 81 86 * Make call identifying target USB device and type of transfer. 82 87 */ 83 aid_t opening_request = async_send_ 4(pipe->hc_phone,88 aid_t opening_request = async_send_3(pipe->hc_phone, 84 89 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 85 90 pipe->wire->address, pipe->endpoint_no, 86 pipe->max_packet_size,87 91 NULL); 88 92 if (opening_request == 0) { 93 pipe_end_transaction(pipe); 89 94 return ENOMEM; 90 95 } … … 96 101 aid_t data_request = async_data_read(pipe->hc_phone, buffer, size, 97 102 &data_request_call); 103 104 /* 105 * Since now on, someone else might access the backing phone 106 * without breaking the transfer IPC protocol. 107 */ 108 pipe_end_transaction(pipe); 98 109 99 110 if (data_request == 0) { … … 146 157 147 158 if (buffer == NULL) { 148 return EINVAL;159 return EINVAL; 149 160 } 150 161 151 162 if (size == 0) { 152 163 return EINVAL; 153 }154 155 if (!usb_pipe_is_session_started(pipe)) {156 return EBADF;157 164 } 158 165 … … 165 172 } 166 173 174 int rc; 175 rc = pipe_add_ref(pipe); 176 if (rc != EOK) { 177 return rc; 178 } 179 180 167 181 size_t act_size = 0; 168 int rc;169 182 170 183 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size); 184 185 pipe_drop_ref(pipe); 186 171 187 if (rc != EOK) { 172 188 return rc; … … 210 226 } 211 227 228 /* Ensure serialization over the phone. */ 229 pipe_start_transaction(pipe); 230 212 231 /* 213 232 * Make call identifying target USB device and type of transfer. 214 233 */ 215 aid_t opening_request = async_send_ 4(pipe->hc_phone,234 aid_t opening_request = async_send_3(pipe->hc_phone, 216 235 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 217 236 pipe->wire->address, pipe->endpoint_no, 218 pipe->max_packet_size,219 237 NULL); 220 238 if (opening_request == 0) { 239 pipe_end_transaction(pipe); 221 240 return ENOMEM; 222 241 } … … 226 245 */ 227 246 int rc = async_data_write_start(pipe->hc_phone, buffer, size); 247 248 /* 249 * Since now on, someone else might access the backing phone 250 * without breaking the transfer IPC protocol. 251 */ 252 pipe_end_transaction(pipe); 253 228 254 if (rc != EOK) { 229 255 async_wait_for(opening_request, NULL); … … 260 286 } 261 287 262 if (!usb_pipe_is_session_started(pipe)) {263 return EBADF;264 }265 266 288 if (pipe->direction != USB_DIRECTION_OUT) { 267 289 return EBADF; … … 272 294 } 273 295 274 int rc = usb_pipe_write_no_check(pipe, buffer, size); 296 int rc; 297 298 rc = pipe_add_ref(pipe); 299 if (rc != EOK) { 300 return rc; 301 } 302 303 rc = usb_pipe_write_no_check(pipe, buffer, size); 304 305 pipe_drop_ref(pipe); 275 306 276 307 return rc; 308 } 309 310 /** Try to clear endpoint halt of default control pipe. 311 * 312 * @param pipe Pipe for control endpoint zero. 313 */ 314 static void clear_self_endpoint_halt(usb_pipe_t *pipe) 315 { 316 assert(pipe != NULL); 317 318 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) { 319 return; 320 } 321 322 323 /* Prevent indefinite recursion. */ 324 pipe->auto_reset_halt = false; 325 usb_request_clear_endpoint_halt(pipe, 0); 326 pipe->auto_reset_halt = true; 277 327 } 278 328 … … 293 343 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size) 294 344 { 345 /* Ensure serialization over the phone. */ 346 pipe_start_transaction(pipe); 347 295 348 /* 296 349 * Make call identifying target USB device and control transfer type. 297 350 */ 298 aid_t opening_request = async_send_ 4(pipe->hc_phone,351 aid_t opening_request = async_send_3(pipe->hc_phone, 299 352 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ, 300 353 pipe->wire->address, pipe->endpoint_no, 301 pipe->max_packet_size,302 354 NULL); 303 355 if (opening_request == 0) { … … 311 363 setup_buffer, setup_buffer_size); 312 364 if (rc != EOK) { 365 pipe_end_transaction(pipe); 313 366 async_wait_for(opening_request, NULL); 314 367 return rc; … … 322 375 data_buffer, data_buffer_size, 323 376 &data_request_call); 377 378 /* 379 * Since now on, someone else might access the backing phone 380 * without breaking the transfer IPC protocol. 381 */ 382 pipe_end_transaction(pipe); 383 384 324 385 if (data_request == 0) { 325 386 async_wait_for(opening_request, NULL); … … 379 440 } 380 441 381 if (!usb_pipe_is_session_started(pipe)) {382 return EBADF;383 }384 385 442 if ((pipe->direction != USB_DIRECTION_BOTH) 386 443 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 388 445 } 389 446 447 int rc; 448 449 rc = pipe_add_ref(pipe); 450 if (rc != EOK) { 451 return rc; 452 } 453 390 454 size_t act_size = 0; 391 intrc = usb_pipe_control_read_no_check(pipe,455 rc = usb_pipe_control_read_no_check(pipe, 392 456 setup_buffer, setup_buffer_size, 393 457 data_buffer, data_buffer_size, &act_size); 458 459 if (rc == ESTALL) { 460 clear_self_endpoint_halt(pipe); 461 } 462 463 pipe_drop_ref(pipe); 394 464 395 465 if (rc != EOK) { … … 418 488 void *data_buffer, size_t data_buffer_size) 419 489 { 490 /* Ensure serialization over the phone. */ 491 pipe_start_transaction(pipe); 492 420 493 /* 421 494 * Make call identifying target USB device and control transfer type. 422 495 */ 423 aid_t opening_request = async_send_ 5(pipe->hc_phone,496 aid_t opening_request = async_send_4(pipe->hc_phone, 424 497 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE, 425 498 pipe->wire->address, pipe->endpoint_no, 426 499 data_buffer_size, 427 pipe->max_packet_size,428 500 NULL); 429 501 if (opening_request == 0) { 502 pipe_end_transaction(pipe); 430 503 return ENOMEM; 431 504 } … … 437 510 setup_buffer, setup_buffer_size); 438 511 if (rc != EOK) { 512 pipe_end_transaction(pipe); 439 513 async_wait_for(opening_request, NULL); 440 514 return rc; … … 447 521 rc = async_data_write_start(pipe->hc_phone, 448 522 data_buffer, data_buffer_size); 523 524 /* All data sent, pipe can be released. */ 525 pipe_end_transaction(pipe); 526 449 527 if (rc != EOK) { 450 528 async_wait_for(opening_request, NULL); 451 529 return rc; 452 530 } 531 } else { 532 /* No data to send, we can release the pipe for others. */ 533 pipe_end_transaction(pipe); 453 534 } 454 535 … … 491 572 } 492 573 493 if (!usb_pipe_is_session_started(pipe)) {494 return EBADF;495 }496 497 574 if ((pipe->direction != USB_DIRECTION_BOTH) 498 575 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 500 577 } 501 578 502 int rc = usb_pipe_control_write_no_check(pipe, 579 int rc; 580 581 rc = pipe_add_ref(pipe); 582 if (rc != EOK) { 583 return rc; 584 } 585 586 rc = usb_pipe_control_write_no_check(pipe, 503 587 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 588 589 if (rc == ESTALL) { 590 clear_self_endpoint_halt(pipe); 591 } 592 593 pipe_drop_ref(pipe); 504 594 505 595 return rc; -
uspace/lib/usb/src/recognise.c
ref354b6 re50cd7f 404 404 child->driver_data = dev_data; 405 405 406 rc = usb_pipe_start_session(&ctrl_pipe);407 if (rc != EOK) {408 goto failure;409 }410 411 406 rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids); 412 if (rc != EOK) {413 goto failure;414 }415 416 rc = usb_pipe_end_session(&ctrl_pipe);417 407 if (rc != EOK) { 418 408 goto failure; -
uspace/lib/usb/src/request.c
ref354b6 re50cd7f 871 871 } 872 872 873 /** Clear halt bit of an endpoint pipe (after pipe stall). 874 * 875 * @param pipe Control pipe. 876 * @param ep_index Endpoint index (in native endianness). 877 * @return Error code. 878 */ 879 int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index) 880 { 881 return usb_request_clear_feature(pipe, 882 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT, 883 uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT), 884 uint16_host2usb(ep_index)); 885 } 886 873 887 /** 874 888 * @}
Note:
See TracChangeset
for help on using the changeset viewer.
