Changeset b4b534ac in mainline for uspace/lib
- Timestamp:
- 2016-07-22T08:24:47Z (9 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f76d2c2
- Parents:
- 5b18137 (diff), 8351f9a4 (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:
-
- 7 added
- 8 deleted
- 53 edited
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/l18n/langs.c
r5b18137 rb4b534ac 66 66 case L18N_WIN_LOCALE_ZULU: 67 67 return "Zulu"; 68 default: 69 break; 68 70 } 69 71 -
uspace/lib/c/include/adt/list.h
r5b18137 rb4b534ac 133 133 134 134 /** Returns true if the link is definitely part of a list. False if not sure. */ 135 static inline bool link_in_use( link_t *link)135 static inline bool link_in_use(const link_t *link) 136 136 { 137 137 return link->prev != NULL && link->next != NULL; … … 263 263 * 264 264 */ 265 static inline link_t *list_last( list_t *list)265 static inline link_t *list_last(const list_t *list) 266 266 { 267 267 return (list->head.prev == &list->head) ? NULL : list->head.prev; … … 276 276 * 277 277 */ 278 static inline link_t *list_next( link_t *link, const list_t *list)278 static inline link_t *list_next(const link_t *link, const list_t *list) 279 279 { 280 280 return (link->next == &list->head) ? NULL : link->next; … … 289 289 * 290 290 */ 291 static inline link_t *list_prev( link_t *link, const list_t *list)291 static inline link_t *list_prev(const link_t *link, const list_t *list) 292 292 { 293 293 return (link->prev == &list->head) ? NULL : link->prev; … … 357 357 * 358 358 */ 359 static inline link_t *list_nth( list_t *list, unsigned long n)359 static inline link_t *list_nth(const list_t *list, unsigned long n) 360 360 { 361 361 unsigned long cnt = 0; -
uspace/lib/c/include/l18n/langs.h
r5b18137 rb4b534ac 54 54 L18N_WIN_LOCALE_SPANISH_TRADITIONAL = 0x040A, 55 55 /* ... */ 56 L18N_WIN_LOCALE_ZULU = 0x0435 56 L18N_WIN_LOCALE_ZULU = 0x0435, 57 L18N_WIN_LOCALE_MAX = 0xFFFF 57 58 } l18_win_locales_t; 58 59 -
uspace/lib/c/include/macros.h
r5b18137 rb4b534ac 69 69 #define PADD8 _padd(8, __LINE__) 70 70 71 #define STATIC_ASSERT(cond) int sassert[(cond) ? 1 : -1] 72 71 73 /** @} 72 74 */ -
uspace/lib/drv/generic/driver.c
r5b18137 rb4b534ac 786 786 assert(fun->bound == false); 787 787 assert(fun->name != NULL); 788 assert(fun->dev != NULL); 788 789 789 790 add_to_functions_list(fun); … … 890 891 891 892 /** Set function ops. */ 892 void ddf_fun_set_ops(ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)893 void ddf_fun_set_ops(ddf_fun_t *fun, const ddf_dev_ops_t *dev_ops) 893 894 { 894 895 assert(fun->conn_handler == NULL); -
uspace/lib/drv/generic/private/driver.h
r5b18137 rb4b534ac 93 93 94 94 /** Implementation of operations provided by this function */ 95 ddf_dev_ops_t *ops;95 const ddf_dev_ops_t *ops; 96 96 97 97 /** Connection handler or @c NULL to use the DDF default handler. */ -
uspace/lib/drv/generic/remote_usb.c
r5b18137 rb4b534ac 35 35 36 36 #include <async.h> 37 #include <macros.h> 37 38 #include <errno.h> 38 #include < macros.h>39 #include <devman.h> 39 40 40 41 #include "usb_iface.h" 41 42 #include "ddf/driver.h" 42 43 44 45 usb_dev_session_t *usb_dev_connect(devman_handle_t handle) 46 { 47 return devman_device_connect(handle, IPC_FLAG_BLOCKING); 48 } 49 50 usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev) 51 { 52 return devman_parent_device_connect(ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING); 53 } 54 55 void usb_dev_disconnect(usb_dev_session_t *sess) 56 { 57 if (sess) 58 async_hangup(sess); 59 } 60 43 61 typedef enum { 44 IPC_M_USB_GET_MY_ADDRESS,45 62 IPC_M_USB_GET_MY_INTERFACE, 46 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, 63 IPC_M_USB_GET_MY_DEVICE_HANDLE, 64 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, 65 IPC_M_USB_RELEASE_DEFAULT_ADDRESS, 66 IPC_M_USB_DEVICE_ENUMERATE, 67 IPC_M_USB_DEVICE_REMOVE, 68 IPC_M_USB_REGISTER_ENDPOINT, 69 IPC_M_USB_UNREGISTER_ENDPOINT, 70 IPC_M_USB_READ, 71 IPC_M_USB_WRITE, 47 72 } usb_iface_funcs_t; 48 49 /** Tell USB address assigned to device.50 * @param exch Vaid IPC exchange51 * @param address Pointer to address storage place.52 * @return Error code.53 *54 * Exch param is an open communication to device implementing usb_iface.55 */56 int usb_get_my_address(async_exch_t *exch, usb_address_t *address)57 {58 if (!exch)59 return EBADMEM;60 sysarg_t addr;61 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),62 IPC_M_USB_GET_MY_ADDRESS, &addr);63 64 if (ret == EOK && address != NULL)65 *address = (usb_address_t) addr;66 return ret;67 }68 73 69 74 /** Tell interface number given device can use. … … 85 90 } 86 91 87 /** Tell devman handle of device host controller.92 /** Tell devman handle of the usb device function. 88 93 * @param[in] exch IPC communication exchange 89 * @param[out] h c_handle devman handle of the HC used by the target device.94 * @param[out] handle devman handle of the HC used by the target device. 90 95 * @return Error code. 91 96 */ 92 int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle) 93 { 94 if (!exch) 95 return EBADMEM; 96 devman_handle_t h; 97 int usb_get_my_device_handle(async_exch_t *exch, devman_handle_t *handle) 98 { 99 devman_handle_t h = 0; 97 100 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 98 IPC_M_USB_GET_ HOST_CONTROLLER_HANDLE, &h);99 if (ret == EOK && h c_handle)100 *h c_handle = (devman_handle_t)h;101 IPC_M_USB_GET_MY_DEVICE_HANDLE, &h); 102 if (ret == EOK && handle) 103 *handle = (devman_handle_t)h; 101 104 return ret; 102 105 } 103 106 104 105 static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 107 /** Reserve default USB address. 108 * @param[in] exch IPC communication exchange 109 * @param[in] speed Communication speed of the newly attached device 110 * @return Error code. 111 */ 112 int usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed) 113 { 114 if (!exch) 115 return EBADMEM; 116 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 117 IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed); 118 } 119 120 /** Release default USB address. 121 * @param[in] exch IPC communication exchange 122 * @return Error code. 123 */ 124 int usb_release_default_address(async_exch_t *exch) 125 { 126 if (!exch) 127 return EBADMEM; 128 return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 129 IPC_M_USB_RELEASE_DEFAULT_ADDRESS); 130 } 131 132 /** Trigger USB device enumeration 133 * @param[in] exch IPC communication exchange 134 * @param[out] handle Identifier of the newly added device (if successful) 135 * @return Error code. 136 */ 137 int usb_device_enumerate(async_exch_t *exch, unsigned port) 138 { 139 if (!exch) 140 return EBADMEM; 141 const int ret = async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 142 IPC_M_USB_DEVICE_ENUMERATE, port); 143 return ret; 144 } 145 146 /** Trigger USB device enumeration 147 * @param[in] exch IPC communication exchange 148 * @param[in] handle Identifier of the device 149 * @return Error code. 150 */ 151 int usb_device_remove(async_exch_t *exch, unsigned port) 152 { 153 if (!exch) 154 return EBADMEM; 155 return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 156 IPC_M_USB_DEVICE_REMOVE, port); 157 } 158 159 int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1]; 160 typedef union { 161 uint8_t arr[sizeof(sysarg_t)]; 162 sysarg_t arg; 163 } pack8_t; 164 165 int usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint, 166 usb_transfer_type_t type, usb_direction_t direction, 167 size_t mps, unsigned packets, unsigned interval) 168 { 169 if (!exch) 170 return EBADMEM; 171 pack8_t pack; 172 pack.arr[0] = type; 173 pack.arr[1] = direction; 174 pack.arr[2] = interval; 175 pack.arr[3] = packets; 176 177 return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 178 IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps); 179 180 } 181 182 int usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint, 183 usb_direction_t direction) 184 { 185 if (!exch) 186 return EBADMEM; 187 return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 188 IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction); 189 } 190 191 int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 192 void *data, size_t size, size_t *rec_size) 193 { 194 if (!exch) 195 return EBADMEM; 196 197 if (size == 0 && setup == 0) 198 return EOK; 199 200 /* Make call identifying target USB device and type of transfer. */ 201 aid_t opening_request = async_send_4(exch, 202 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint, 203 (setup & UINT32_MAX), (setup >> 32), NULL); 204 205 if (opening_request == 0) { 206 return ENOMEM; 207 } 208 209 /* Retrieve the data. */ 210 ipc_call_t data_request_call; 211 aid_t data_request = 212 async_data_read(exch, data, size, &data_request_call); 213 214 if (data_request == 0) { 215 // FIXME: How to let the other side know that we want to abort? 216 async_forget(opening_request); 217 return ENOMEM; 218 } 219 220 /* Wait for the answer. */ 221 sysarg_t data_request_rc; 222 sysarg_t opening_request_rc; 223 async_wait_for(data_request, &data_request_rc); 224 async_wait_for(opening_request, &opening_request_rc); 225 226 if (data_request_rc != EOK) { 227 /* Prefer the return code of the opening request. */ 228 if (opening_request_rc != EOK) { 229 return (int) opening_request_rc; 230 } else { 231 return (int) data_request_rc; 232 } 233 } 234 if (opening_request_rc != EOK) { 235 return (int) opening_request_rc; 236 } 237 238 *rec_size = IPC_GET_ARG2(data_request_call); 239 return EOK; 240 } 241 242 int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup, 243 const void *data, size_t size) 244 { 245 if (!exch) 246 return EBADMEM; 247 248 if (size == 0 && setup == 0) 249 return EOK; 250 251 aid_t opening_request = async_send_5(exch, 252 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size, 253 (setup & UINT32_MAX), (setup >> 32), NULL); 254 255 if (opening_request == 0) { 256 return ENOMEM; 257 } 258 259 /* Send the data if any. */ 260 if (size > 0) { 261 const int ret = async_data_write_start(exch, data, size); 262 if (ret != EOK) { 263 async_forget(opening_request); 264 return ret; 265 } 266 } 267 268 /* Wait for the answer. */ 269 sysarg_t opening_request_rc; 270 async_wait_for(opening_request, &opening_request_rc); 271 272 return (int) opening_request_rc; 273 } 274 106 275 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 107 static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 276 static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 277 static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 278 static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 279 static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 280 static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 281 static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 282 static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 283 static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 284 static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call); 108 285 109 286 /** Remote USB interface operations. */ 110 287 static const remote_iface_func_ptr_t remote_usb_iface_ops [] = { 111 [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,112 288 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface, 113 [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle, 289 [IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle, 290 [IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address, 291 [IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address, 292 [IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate, 293 [IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove, 294 [IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint, 295 [IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint, 296 [IPC_M_USB_READ] = remote_usb_read, 297 [IPC_M_USB_WRITE] = remote_usb_write, 114 298 }; 115 299 … … 118 302 const remote_iface_t remote_usb_iface = { 119 303 .method_count = ARRAY_SIZE(remote_usb_iface_ops), 120 .methods = remote_usb_iface_ops 304 .methods = remote_usb_iface_ops, 121 305 }; 122 123 124 void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,125 ipc_callid_t callid, ipc_call_t *call)126 {127 const usb_iface_t *usb_iface = (usb_iface_t *) iface;128 129 if (usb_iface->get_my_address == NULL) {130 async_answer_0(callid, ENOTSUP);131 return;132 }133 134 usb_address_t address;135 const int ret = usb_iface->get_my_address(fun, &address);136 if (ret != EOK) {137 async_answer_0(callid, ret);138 } else {139 async_answer_1(callid, EOK, address);140 }141 }142 306 143 307 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface, … … 160 324 } 161 325 162 void remote_usb_get_ hc_handle(ddf_fun_t *fun, void *iface,326 void remote_usb_get_my_device_handle(ddf_fun_t *fun, void *iface, 163 327 ipc_callid_t callid, ipc_call_t *call) 164 328 { 165 329 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 166 330 167 if (usb_iface->get_ hc_handle == NULL) {331 if (usb_iface->get_my_device_handle == NULL) { 168 332 async_answer_0(callid, ENOTSUP); 169 333 return; … … 171 335 172 336 devman_handle_t handle; 173 const int ret = usb_iface->get_ hc_handle(fun, &handle);337 const int ret = usb_iface->get_my_device_handle(fun, &handle); 174 338 if (ret != EOK) { 175 339 async_answer_0(callid, ret); … … 178 342 async_answer_1(callid, EOK, (sysarg_t) handle); 179 343 } 344 345 void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface, 346 ipc_callid_t callid, ipc_call_t *call) 347 { 348 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 349 350 if (usb_iface->reserve_default_address == NULL) { 351 async_answer_0(callid, ENOTSUP); 352 return; 353 } 354 355 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 356 const int ret = usb_iface->reserve_default_address(fun, speed); 357 async_answer_0(callid, ret); 358 } 359 360 void remote_usb_release_default_address(ddf_fun_t *fun, void *iface, 361 ipc_callid_t callid, ipc_call_t *call) 362 { 363 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 364 365 if (usb_iface->release_default_address == NULL) { 366 async_answer_0(callid, ENOTSUP); 367 return; 368 } 369 370 const int ret = usb_iface->release_default_address(fun); 371 async_answer_0(callid, ret); 372 } 373 374 static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface, 375 ipc_callid_t callid, ipc_call_t *call) 376 { 377 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 378 379 if (usb_iface->device_enumerate == NULL) { 380 async_answer_0(callid, ENOTSUP); 381 return; 382 } 383 384 const unsigned port = DEV_IPC_GET_ARG1(*call); 385 const int ret = usb_iface->device_enumerate(fun, port); 386 async_answer_0(callid, ret); 387 } 388 389 static void remote_usb_device_remove(ddf_fun_t *fun, void *iface, 390 ipc_callid_t callid, ipc_call_t *call) 391 { 392 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 393 394 if (usb_iface->device_remove == NULL) { 395 async_answer_0(callid, ENOTSUP); 396 return; 397 } 398 399 const unsigned port = DEV_IPC_GET_ARG1(*call); 400 const int ret = usb_iface->device_remove(fun, port); 401 async_answer_0(callid, ret); 402 } 403 404 static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface, 405 ipc_callid_t callid, ipc_call_t *call) 406 { 407 usb_iface_t *usb_iface = (usb_iface_t *) iface; 408 409 if (!usb_iface->register_endpoint) { 410 async_answer_0(callid, ENOTSUP); 411 return; 412 } 413 414 const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call); 415 const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)}; 416 const size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 417 418 const usb_transfer_type_t transfer_type = pack.arr[0]; 419 const usb_direction_t direction = pack.arr[1]; 420 unsigned packets = pack.arr[2]; 421 unsigned interval = pack.arr[3]; 422 423 const int ret = usb_iface->register_endpoint(fun, endpoint, 424 transfer_type, direction, max_packet_size, packets, interval); 425 426 async_answer_0(callid, ret); 427 } 428 429 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface, 430 ipc_callid_t callid, ipc_call_t *call) 431 { 432 usb_iface_t *usb_iface = (usb_iface_t *) iface; 433 434 if (!usb_iface->unregister_endpoint) { 435 async_answer_0(callid, ENOTSUP); 436 return; 437 } 438 439 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call); 440 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call); 441 442 int rc = usb_iface->unregister_endpoint(fun, endpoint, direction); 443 444 async_answer_0(callid, rc); 445 } 446 447 typedef struct { 448 ipc_callid_t caller; 449 ipc_callid_t data_caller; 450 void *buffer; 451 } async_transaction_t; 452 453 static void async_transaction_destroy(async_transaction_t *trans) 454 { 455 if (trans == NULL) { 456 return; 457 } 458 if (trans->buffer != NULL) { 459 free(trans->buffer); 460 } 461 462 free(trans); 463 } 464 465 static async_transaction_t *async_transaction_create(ipc_callid_t caller) 466 { 467 async_transaction_t *trans = malloc(sizeof(async_transaction_t)); 468 if (trans == NULL) { 469 return NULL; 470 } 471 472 trans->caller = caller; 473 trans->data_caller = 0; 474 trans->buffer = NULL; 475 476 return trans; 477 } 478 479 static void callback_out(int outcome, void *arg) 480 { 481 async_transaction_t *trans = arg; 482 483 async_answer_0(trans->caller, outcome); 484 485 async_transaction_destroy(trans); 486 } 487 488 static void callback_in(int outcome, size_t actual_size, void *arg) 489 { 490 async_transaction_t *trans = (async_transaction_t *)arg; 491 492 if (outcome != EOK) { 493 async_answer_0(trans->caller, outcome); 494 if (trans->data_caller) { 495 async_answer_0(trans->data_caller, EINTR); 496 } 497 async_transaction_destroy(trans); 498 return; 499 } 500 501 if (trans->data_caller) { 502 async_data_read_finalize(trans->data_caller, 503 trans->buffer, actual_size); 504 } 505 506 async_answer_0(trans->caller, EOK); 507 508 async_transaction_destroy(trans); 509 } 510 511 void remote_usb_read( 512 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 513 { 514 assert(fun); 515 assert(iface); 516 assert(call); 517 518 const usb_iface_t *usb_iface = iface; 519 520 if (!usb_iface->read) { 521 async_answer_0(callid, ENOTSUP); 522 return; 523 } 524 525 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 526 const uint64_t setup = 527 ((uint64_t)DEV_IPC_GET_ARG2(*call)) | 528 (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32); 529 530 async_transaction_t *trans = async_transaction_create(callid); 531 if (trans == NULL) { 532 async_answer_0(callid, ENOMEM); 533 return; 534 } 535 536 size_t size = 0; 537 if (!async_data_read_receive(&trans->data_caller, &size)) { 538 async_answer_0(callid, EPARTY); 539 return; 540 } 541 542 trans->buffer = malloc(size); 543 if (trans->buffer == NULL) { 544 async_answer_0(trans->data_caller, ENOMEM); 545 async_answer_0(callid, ENOMEM); 546 async_transaction_destroy(trans); 547 } 548 549 const int rc = usb_iface->read( 550 fun, ep, setup, trans->buffer, size, callback_in, trans); 551 552 if (rc != EOK) { 553 async_answer_0(trans->data_caller, rc); 554 async_answer_0(callid, rc); 555 async_transaction_destroy(trans); 556 } 557 } 558 559 void remote_usb_write( 560 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) 561 { 562 assert(fun); 563 assert(iface); 564 assert(call); 565 566 const usb_iface_t *usb_iface = iface; 567 568 if (!usb_iface->write) { 569 async_answer_0(callid, ENOTSUP); 570 return; 571 } 572 573 const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call); 574 const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call); 575 const uint64_t setup = 576 ((uint64_t)DEV_IPC_GET_ARG3(*call)) | 577 (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32); 578 579 async_transaction_t *trans = async_transaction_create(callid); 580 if (trans == NULL) { 581 async_answer_0(callid, ENOMEM); 582 return; 583 } 584 585 size_t size = 0; 586 if (data_buffer_len > 0) { 587 const int rc = async_data_write_accept(&trans->buffer, false, 588 1, data_buffer_len, 0, &size); 589 590 if (rc != EOK) { 591 async_answer_0(callid, rc); 592 async_transaction_destroy(trans); 593 return; 594 } 595 } 596 597 const int rc = usb_iface->write( 598 fun, ep, setup, trans->buffer, size, callback_out, trans); 599 600 if (rc != EOK) { 601 async_answer_0(callid, rc); 602 async_transaction_destroy(trans); 603 } 604 } 180 605 /** 181 606 * @} -
uspace/lib/drv/generic/remote_usbhc.c
r5b18137 rb4b534ac 85 85 */ 86 86 typedef enum { 87 /** Asks for address assignment by host controller.88 * Answer:89 * - ELIMIT - host controller run out of address90 * - EOK - address assigned91 * Answer arguments:92 * - assigned address93 *94 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS.95 */96 IPC_M_USBHC_REQUEST_ADDRESS,97 98 /** Bind USB address with devman handle.99 * Parameters:100 * - USB address101 * - devman handle102 * Answer:103 * - EOK - address binded104 * - ENOENT - address is not in use105 */106 IPC_M_USBHC_BIND_ADDRESS,107 108 /** Get handle binded with given USB address.109 * Parameters110 * - USB address111 * Answer:112 * - EOK - address binded, first parameter is the devman handle113 * - ENOENT - address is not in use at the moment114 */115 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,116 117 /** Release address in use.118 * Arguments:119 * - address to be released120 * Answer:121 * - ENOENT - address not in use122 * - EPERM - trying to release default USB address123 */124 IPC_M_USBHC_RELEASE_ADDRESS,125 126 /** Register endpoint attributes at host controller.127 * This is used to reserve portion of USB bandwidth.128 * When speed is invalid, speed of the device is used.129 * Parameters:130 * - USB address + endpoint number131 * - packed as ADDR << 16 + EP132 * - speed + transfer type + direction133 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR134 * - maximum packet size + interval (in milliseconds)135 * - packed as MPS << 16 + INT136 * Answer:137 * - EOK - reservation successful138 * - ELIMIT - not enough bandwidth to satisfy the request139 */140 IPC_M_USBHC_REGISTER_ENDPOINT,141 142 /** Revert endpoint registration.143 * Parameters:144 * - USB address145 * - endpoint number146 * - data direction147 * Answer:148 * - EOK - endpoint unregistered149 * - ENOENT - unknown endpoint150 */151 IPC_M_USBHC_UNREGISTER_ENDPOINT,152 153 87 /** Get data from device. 154 88 * See explanation at usb_iface_funcs_t (IN transaction). … … 161 95 IPC_M_USBHC_WRITE, 162 96 } usbhc_iface_funcs_t; 163 164 int usbhc_request_address(async_exch_t *exch, usb_address_t *address,165 bool strict, usb_speed_t speed)166 {167 if (!exch || !address)168 return EBADMEM;169 sysarg_t new_address;170 const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),171 IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address);172 if (ret == EOK)173 *address = (usb_address_t)new_address;174 return ret;175 }176 177 int usbhc_bind_address(async_exch_t *exch, usb_address_t address,178 devman_handle_t handle)179 {180 if (!exch)181 return EBADMEM;182 return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),183 IPC_M_USBHC_BIND_ADDRESS, address, handle);184 }185 186 int usbhc_get_handle(async_exch_t *exch, usb_address_t address,187 devman_handle_t *handle)188 {189 if (!exch)190 return EBADMEM;191 sysarg_t h;192 const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),193 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h);194 if (ret == EOK && handle)195 *handle = (devman_handle_t)h;196 return ret;197 }198 199 int usbhc_release_address(async_exch_t *exch, usb_address_t address)200 {201 if (!exch)202 return EBADMEM;203 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),204 IPC_M_USBHC_RELEASE_ADDRESS, address);205 }206 207 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address,208 usb_endpoint_t endpoint, usb_transfer_type_t type,209 usb_direction_t direction, size_t mps, unsigned interval)210 {211 if (!exch)212 return EBADMEM;213 const usb_target_t target =214 {{ .address = address, .endpoint = endpoint }};215 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))216 217 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),218 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,219 _PACK2(type, direction), _PACK2(mps, interval));220 221 #undef _PACK2222 }223 224 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,225 usb_endpoint_t endpoint, usb_direction_t direction)226 {227 if (!exch)228 return EBADMEM;229 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),230 IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);231 }232 97 233 98 int usbhc_read(async_exch_t *exch, usb_address_t address, … … 323 188 } 324 189 325 326 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);327 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);328 static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);329 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);330 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);331 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);332 190 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 333 191 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 334 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);335 192 336 193 /** Remote USB host controller interface operations. */ 337 194 static const remote_iface_func_ptr_t remote_usbhc_iface_ops[] = { 338 [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,339 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,340 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,341 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle,342 343 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,344 [IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,345 346 195 [IPC_M_USBHC_READ] = remote_usbhc_read, 347 196 [IPC_M_USBHC_WRITE] = remote_usbhc_write, … … 386 235 } 387 236 388 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 389 ipc_callid_t callid, ipc_call_t *call) 390 { 391 const usbhc_iface_t *usb_iface = iface; 392 393 if (!usb_iface->request_address) { 394 async_answer_0(callid, ENOTSUP); 395 return; 396 } 397 398 usb_address_t address = DEV_IPC_GET_ARG1(*call); 399 const bool strict = DEV_IPC_GET_ARG2(*call); 400 const usb_speed_t speed = DEV_IPC_GET_ARG3(*call); 401 402 const int rc = usb_iface->request_address(fun, &address, strict, speed); 403 if (rc != EOK) { 404 async_answer_0(callid, rc); 405 } else { 406 async_answer_1(callid, EOK, (sysarg_t) address); 407 } 408 } 409 410 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 411 ipc_callid_t callid, ipc_call_t *call) 412 { 413 const usbhc_iface_t *usb_iface = iface; 414 415 if (!usb_iface->bind_address) { 416 async_answer_0(callid, ENOTSUP); 417 return; 418 } 419 420 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 421 const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 422 423 const int ret = usb_iface->bind_address(fun, address, handle); 424 async_answer_0(callid, ret); 425 } 426 427 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface, 428 ipc_callid_t callid, ipc_call_t *call) 429 { 430 const usbhc_iface_t *usb_iface = iface; 431 432 if (!usb_iface->get_handle) { 433 async_answer_0(callid, ENOTSUP); 434 return; 435 } 436 437 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 438 devman_handle_t handle; 439 const int ret = usb_iface->get_handle(fun, address, &handle); 440 441 if (ret == EOK) { 442 async_answer_1(callid, ret, handle); 443 } else { 444 async_answer_0(callid, ret); 445 } 446 } 447 448 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 449 ipc_callid_t callid, ipc_call_t *call) 450 { 451 const usbhc_iface_t *usb_iface = iface; 452 453 if (!usb_iface->release_address) { 454 async_answer_0(callid, ENOTSUP); 455 return; 456 } 457 458 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 459 460 const int ret = usb_iface->release_address(fun, address); 461 async_answer_0(callid, ret); 462 } 463 464 static void callback_out(ddf_fun_t *fun, 465 int outcome, void *arg) 237 static void callback_out(int outcome, void *arg) 466 238 { 467 239 async_transaction_t *trans = arg; … … 472 244 } 473 245 474 static void callback_in(ddf_fun_t *fun, 475 int outcome, size_t actual_size, void *arg) 246 static void callback_in(int outcome, size_t actual_size, void *arg) 476 247 { 477 248 async_transaction_t *trans = (async_transaction_t *)arg; … … 496 267 } 497 268 498 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,499 ipc_callid_t callid, ipc_call_t *call)500 {501 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;502 503 if (!usb_iface->register_endpoint) {504 async_answer_0(callid, ENOTSUP);505 return;506 }507 508 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \509 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16)510 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \511 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff)512 513 const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };514 515 _INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2);516 _INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2);517 518 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);519 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3);520 521 #undef _INIT_FROM_HIGH_DATA2522 #undef _INIT_FROM_LOW_DATA2523 524 int rc = usb_iface->register_endpoint(fun, target.address,525 target.endpoint, transfer_type, direction, max_packet_size, interval);526 527 async_answer_0(callid, rc);528 }529 530 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,531 ipc_callid_t callid, ipc_call_t *call)532 {533 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;534 535 if (!usb_iface->unregister_endpoint) {536 async_answer_0(callid, ENOTSUP);537 return;538 }539 540 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);541 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);542 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);543 544 int rc = usb_iface->unregister_endpoint(fun,545 address, endpoint, direction);546 547 async_answer_0(callid, rc);548 }549 550 269 void remote_usbhc_read( 551 270 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) -
uspace/lib/drv/include/ddf/driver.h
r5b18137 rb4b534ac 132 132 extern int ddf_fun_offline(ddf_fun_t *); 133 133 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int); 134 extern void ddf_fun_set_ops(ddf_fun_t *, ddf_dev_ops_t *);134 extern void ddf_fun_set_ops(ddf_fun_t *, const ddf_dev_ops_t *); 135 135 extern void ddf_fun_set_conn_handler(ddf_fun_t *, async_port_handler_t); 136 136 extern int ddf_fun_add_to_category(ddf_fun_t *, const char *); -
uspace/lib/drv/include/usb_iface.h
r5b18137 rb4b534ac 42 42 #include <usb/usb.h> 43 43 44 int usb_get_my_address(async_exch_t *, usb_address_t *); 44 typedef async_sess_t usb_dev_session_t; 45 46 usb_dev_session_t *usb_dev_connect(devman_handle_t); 47 usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *); 48 void usb_dev_disconnect(usb_dev_session_t *); 49 45 50 int usb_get_my_interface(async_exch_t *, int *); 46 int usb_get_hc_handle(async_exch_t *, devman_handle_t *); 51 int usb_get_my_device_handle(async_exch_t *, devman_handle_t *); 52 53 int usb_reserve_default_address(async_exch_t *, usb_speed_t); 54 int usb_release_default_address(async_exch_t *); 55 56 int usb_device_enumerate(async_exch_t *, unsigned port); 57 int usb_device_remove(async_exch_t *, unsigned port); 58 59 int usb_register_endpoint(async_exch_t *, usb_endpoint_t, usb_transfer_type_t, 60 usb_direction_t, size_t, unsigned, unsigned); 61 int usb_unregister_endpoint(async_exch_t *, usb_endpoint_t, usb_direction_t); 62 int usb_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t, size_t *); 63 int usb_write(async_exch_t *, usb_endpoint_t, uint64_t, const void *, size_t); 64 65 /** Callback for outgoing transfer. */ 66 typedef void (*usb_iface_transfer_out_callback_t)(int, void *); 67 68 /** Callback for incoming transfer. */ 69 typedef void (*usb_iface_transfer_in_callback_t)(int, size_t, void *); 47 70 48 71 /** USB device communication interface. */ 49 72 typedef struct { 50 int (*get_my_address)(ddf_fun_t *, usb_address_t *);51 73 int (*get_my_interface)(ddf_fun_t *, int *); 52 int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *); 74 int (*get_my_device_handle)(ddf_fun_t *, devman_handle_t *); 75 76 int (*reserve_default_address)(ddf_fun_t *, usb_speed_t); 77 int (*release_default_address)(ddf_fun_t *); 78 79 int (*device_enumerate)(ddf_fun_t *, unsigned); 80 int (*device_remove)(ddf_fun_t *, unsigned); 81 82 int (*register_endpoint)(ddf_fun_t *, usb_endpoint_t, 83 usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned); 84 int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_t, 85 usb_direction_t); 86 87 int (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t, 88 usb_iface_transfer_in_callback_t, void *); 89 int (*write)(ddf_fun_t *, usb_endpoint_t, uint64_t, const uint8_t *, 90 size_t, usb_iface_transfer_out_callback_t, void *); 53 91 } usb_iface_t; 54 92 -
uspace/lib/drv/include/usbhc_iface.h
r5b18137 rb4b534ac 44 44 #include <stdbool.h> 45 45 46 int usbhc_request_address(async_exch_t *, usb_address_t *, bool, usb_speed_t);47 int usbhc_bind_address(async_exch_t *, usb_address_t, devman_handle_t);48 int usbhc_get_handle(async_exch_t *, usb_address_t, devman_handle_t *);49 int usbhc_release_address(async_exch_t *, usb_address_t);50 int usbhc_register_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,51 usb_transfer_type_t, usb_direction_t, size_t, unsigned int);52 int usbhc_unregister_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,53 usb_direction_t);54 46 int usbhc_read(async_exch_t *, usb_address_t, usb_endpoint_t, 55 47 uint64_t, void *, size_t, size_t *); … … 58 50 59 51 /** Callback for outgoing transfer. */ 60 typedef void (*usbhc_iface_transfer_out_callback_t)( ddf_fun_t *,int, void *);52 typedef void (*usbhc_iface_transfer_out_callback_t)(int, void *); 61 53 62 54 /** Callback for incoming transfer. */ 63 typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *, 64 int, size_t, void *); 55 typedef void (*usbhc_iface_transfer_in_callback_t)(int, size_t, void *); 65 56 66 57 /** USB host controller communication interface. */ 67 58 typedef struct { 68 int (*request_address)(ddf_fun_t *, usb_address_t *, bool, usb_speed_t);69 int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);70 int (*get_handle)(ddf_fun_t *, usb_address_t,71 devman_handle_t *);72 int (*release_address)(ddf_fun_t *, usb_address_t);73 74 int (*register_endpoint)(ddf_fun_t *,75 usb_address_t, usb_endpoint_t,76 usb_transfer_type_t, usb_direction_t, size_t, unsigned int);77 int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,78 usb_direction_t);79 80 59 int (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t, 81 60 usbhc_iface_transfer_in_callback_t, void *); 82 83 61 int (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *, 84 62 size_t, usbhc_iface_transfer_out_callback_t, void *); -
uspace/lib/scsi/include/scsi/spc.h
r5b18137 rb4b534ac 42 42 /** SCSI command codes defined in SCSI-SPC */ 43 43 enum scsi_cmd_spc { 44 SCSI_CMD_INQUIRY = 0x12, 45 SCSI_CMD_REQUEST_SENSE = 0x03 44 SCSI_CMD_TEST_UNIT_READY = 0x00, 45 SCSI_CMD_REQUEST_SENSE = 0x03, 46 SCSI_CMD_INQUIRY = 0x12, 46 47 }; 47 48 … … 220 221 extern const char *scsi_get_sense_key_str(unsigned); 221 222 223 /** SCSI Test Unit Ready command */ 224 typedef struct { 225 /** Operation code (SCSI_CMD_TEST_UNIT_READY) */ 226 uint8_t op_code; 227 /** Reserved */ 228 uint32_t reserved; 229 /* Control */ 230 uint8_t control; 231 } __attribute__((packed)) scsi_cdb_test_unit_ready_t; 232 222 233 #endif 223 234 -
uspace/lib/usb/Makefile
r5b18137 rb4b534ac 36 36 SOURCES = \ 37 37 src/class.c \ 38 src/ddfiface.c \39 38 src/dev.c \ 40 39 src/debug.c \ 41 40 src/dump.c \ 42 src/hc.c \43 41 src/usb.c 44 42 -
uspace/lib/usb/include/usb/classes/hub.h
r5b18137 rb4b534ac 43 43 */ 44 44 typedef enum { 45 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0, 46 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1, 45 47 USB_HUB_FEATURE_HUB_LOCAL_POWER = 0, 46 48 USB_HUB_FEATURE_HUB_OVER_CURRENT = 1, 47 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,48 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,49 49 USB_HUB_FEATURE_PORT_CONNECTION = 0, 50 50 USB_HUB_FEATURE_PORT_ENABLE = 1, … … 54 54 USB_HUB_FEATURE_PORT_POWER = 8, 55 55 USB_HUB_FEATURE_PORT_LOW_SPEED = 9, 56 USB_HUB_FEATURE_PORT_HIGH_SPEED = 10, 56 57 USB_HUB_FEATURE_C_PORT_CONNECTION = 16, 57 58 USB_HUB_FEATURE_C_PORT_ENABLE = 17, … … 59 60 USB_HUB_FEATURE_C_PORT_OVER_CURRENT = 19, 60 61 USB_HUB_FEATURE_C_PORT_RESET = 20, 62 USB_HUB_FEATURE_PORT_TEST = 21, 63 USB_HUB_FEATURE_PORT_INDICATOR = 22 61 64 /* USB_HUB_FEATURE_ = , */ 62 65 } usb_hub_class_feature_t; … … 67 70 /** Descriptor length. */ 68 71 uint8_t length; 72 69 73 /** Descriptor type (0x29). */ 70 74 uint8_t descriptor_type; 75 71 76 /** Number of downstream ports. */ 72 77 uint8_t port_count; 73 /** Characteristics bitmask. */ 78 79 /** Characteristics bitmask. 80 * 81 * D1..D0: Logical Power Switching Mode 82 * 00: Ganged power switching (all ports power at 83 * once) 84 * 01: Individual port power switching 85 * 1X: Reserved. Used only on 1.0 compliant hubs 86 * that implement no power switching. 87 * D2: Identifies a Compound Device 88 * 0: Hub is not part of a compound device 89 * 1: Hub is part of a compound device 90 * D4..D3: Over-current Protection Mode 91 * 00: Global Over-current Protection. The hub 92 * reports over-current as a summation of all 93 * ports current draw, without a breakdown of 94 * individual port over-current status. 95 * 01: Individual Port Over-current Protection. The 96 * hub reports over-current on a per-port basis. 97 * Each port has an over-current indicator. 98 * 1X: No Over-current Protection. This option is 99 * allowed only for bus-powered hubs that do not 100 * implement over-current protection. 101 * D6..D5: TT think time 102 * 00: At most 8 FS bit times 103 * 01: At most 16 FS bit times 104 * 10: At most 24 FS bit times 105 * 11: At most 32 FS bit times 106 * D7: Port indicators 107 * 0: Not supported 108 * 1: Supported 109 * D15...D8: Reserved 110 */ 74 111 uint8_t characteristics; 75 #define HUB_CHAR_POWER_PER_PORT_FLAG (1 << 0) 76 #define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1) 77 /* Unused part of characteristics field */ 112 #define HUB_CHAR_POWER_PER_PORT_FLAG (1 << 0) 113 #define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1) 114 #define HUB_CHAR_COMPOUND_DEVICE (1 << 2) 115 #define HUB_CHAR_OC_PER_PORT_FLAG (1 << 3) 116 #define HUB_CHAR_NO_OC_FLAG (1 << 4) 117 #define HUB_CHAR_TT_THINK_16 (1 << 5) 118 #define HUB_CHAR_TT_THINK_8 (1 << 6) 119 #define HUB_CHAR_INDICATORS_FLAG (1 << 7) 120 121 /** Unused part of characteristics field */ 78 122 uint8_t characteristics_reserved; 79 /** Time from power-on to stabilization of current on the port. */ 123 124 /** Time from power-on to stabilization of current on the port. 125 * 126 * Time (in 2ms intervals) from the time the power-on 127 * sequence begins on a port until power is good on that 128 * port. The USB System Software uses this value to 129 * determine how long to wait before accessing a 130 * powered-on port. 131 */ 80 132 uint8_t power_good_time; 81 /** Maximum current requirements in mA. */ 133 /** Maximum current requirements in mA. 134 * 135 * Maximum current requirements of the Hub Controller 136 * electronics in mA. 137 */ 82 138 uint8_t max_current; 83 139 } __attribute__ ((packed)) usb_hub_descriptor_header_t; 84 140 85 /** 86 * @brief usb hub descriptor 87 * 88 * For more information see Universal Serial Bus Specification Revision 1.1 89 * chapter 11.16.2 90 */ 91 typedef struct usb_hub_descriptor_type { 92 /** Number of bytes in this descriptor, including this byte */ 93 //uint8_t bDescLength; 94 95 /** Descriptor Type, value: 29H for hub descriptor */ 96 //uint8_t bDescriptorType; 97 98 /** Number of downstream ports that this hub supports */ 99 uint8_t port_count; 100 101 /** 102 D1...D0: Logical Power Switching Mode 103 00: Ganged power switching (all ports power at 104 once) 105 01: Individual port power switching 106 1X: Reserved. Used only on 1.0 compliant hubs 107 that implement no power switching. 108 D2: Identifies a Compound Device 109 0: Hub is not part of a compound device 110 1: Hub is part of a compound device 111 D4...D3: Over-current Protection Mode 112 00: Global Over-current Protection. The hub 113 reports over-current as a summation of all 114 ports current draw, without a breakdown of 115 individual port over-current status. 116 01: Individual Port Over-current Protection. The 117 hub reports over-current on a per-port basis. 118 Each port has an over-current indicator. 119 1X: No Over-current Protection. This option is 120 allowed only for bus-powered hubs that do not 121 implement over-current protection. 122 D15...D5: 123 Reserved 124 */ 125 uint16_t hub_characteristics; 126 127 /** 128 Time (in 2ms intervals) from the time the power-on 129 sequence begins on a port until power is good on that 130 port. The USB System Software uses this value to 131 determine how long to wait before accessing a 132 powered-on port. 133 */ 134 uint8_t pwr_on_2_good_time; 135 136 /** 137 Maximum current requirements of the Hub Controller 138 electronics in mA. 139 */ 140 uint8_t current_requirement; 141 142 /** 143 Indicates if a port has a removable device attached. 144 This field is reported on byte-granularity. Within a 145 byte, if no port exists for a given location, the field 146 representing the port characteristics returns 0. 147 Bit value definition: 148 0B - Device is removable 149 1B - Device is non-removable 150 This is a bitmap corresponding to the individual ports 151 on the hub: 152 Bit 0: Reserved for future use 153 Bit 1: Port 1 154 Bit 2: Port 2 155 .... 156 Bit n: Port n (implementation-dependent, up to a 157 maximum of 255 ports). 158 */ 159 uint8_t devices_removable[32]; 160 161 /** 162 This field exists for reasons of compatibility with 163 software written for 1.0 compliant devices. All bits in 164 this field should be set to 1B. This field has one bit for 165 each port on the hub with additional pad bits, if 166 necessary, to make the number of bits in the field an 167 integer multiple of 8. 168 */ 169 //uint8_t * port_pwr_ctrl_mask; 170 } usb_hub_descriptor_t; 171 172 141 /** One bit for the device and one bit for every port */ 142 #define STATUS_BYTES(ports) ((1 + ports + 7) / 8) 173 143 174 144 /** @brief usb hub specific request types. … … 204 174 /** */ 205 175 USB_HUB_REQUEST_CLEAR_FEATURE = 1, 206 /** */176 /** USB 1.0 only */ 207 177 USB_HUB_REQUEST_GET_STATE = 2, 208 178 /** */ … … 211 181 USB_HUB_REQUEST_GET_DESCRIPTOR = 6, 212 182 /** */ 213 USB_HUB_REQUEST_SET_DESCRIPTOR = 7 183 USB_HUB_REQUEST_SET_DESCRIPTOR = 7, 184 /** */ 185 USB_HUB_REQUEST_CLEAR_TT_BUFFER = 8, 186 /** */ 187 USB_HUB_REQUEST_RESET_TT = 9, 188 /** */ 189 USB_HUB_GET_TT_STATE = 10, 190 /** */ 191 USB_HUB_STOP_TT = 11, 214 192 } usb_hub_request_t; 215 193 … … 218 196 */ 219 197 /* 7 (basic size) + 2*32 (port bitmasks) */ 220 #define USB_HUB_MAX_DESCRIPTOR_SIZE 71198 #define USB_HUB_MAX_DESCRIPTOR_SIZE (7 + 2 * 32) 221 199 222 200 #endif -
uspace/lib/usb/include/usb/classes/massstor.h
r5b18137 rb4b534ac 36 36 #define LIBUSB_CLASS_MASSSTOR_H_ 37 37 38 #include <sys/types.h>39 40 38 /** USB mass storage subclasses. */ 41 39 typedef enum { -
uspace/lib/usb/include/usb/debug.h
r5b18137 rb4b534ac 36 36 #define LIBUSB_DEBUG_H_ 37 37 #include <stdio.h> 38 #include <inttypes.h> 39 #include <usb/usb.h> 38 #include <sys/types.h> 40 39 #include <io/log.h> 41 #include <assert.h> 40 42 41 43 42 void usb_dump_standard_descriptor(FILE *, const char *, const char *, -
uspace/lib/usb/include/usb/descriptor.h
r5b18137 rb4b534ac 36 36 #define LIBUSB_DESCRIPTOR_H_ 37 37 38 #include < async.h>38 #include <sys/types.h> 39 39 40 40 /** Descriptor type. */ … … 45 45 USB_DESCTYPE_INTERFACE = 4, 46 46 USB_DESCTYPE_ENDPOINT = 5, 47 /* New in USB2.0 */ 48 USB_DESCTYPE_DEVICE_QUALIFIER = 6, 49 USB_DESCTYPE_OTHER_SPEED_CONFIGURATION = 7, 50 USB_DESCTYPE_INTERFACE_POWER = 8, 51 /* Class specific */ 47 52 USB_DESCTYPE_HID = 0x21, 48 53 USB_DESCTYPE_HID_REPORT = 0x22, … … 89 94 } __attribute__ ((packed)) usb_standard_device_descriptor_t; 90 95 96 /** USB device qualifier decriptor is basically a cut down version of the device 97 * descriptor with values that would be valid if the device operated on the 98 * other speed (HIGH vs. FULL) 99 */ 100 typedef struct { 101 /** Size of this descriptor in bytes */ 102 uint8_t length; 103 /** Descriptor type (USB_DESCTYPE_DEVICE_QUALIFIER) */ 104 uint8_t descriptor_type; 105 /** USB specification release number. 106 * The number shall be coded as binary-coded decimal (BCD). 107 */ 108 uint16_t usb_spec_version; 109 /** Device class. */ 110 uint8_t device_class; 111 /** Device sub-class. */ 112 uint8_t device_subclass; 113 /** Device protocol. */ 114 uint8_t device_protocol; 115 /** Maximum packet size for endpoint zero. 116 * Valid values are only 8, 16, 32, 64). 117 */ 118 uint8_t max_packet_size; 119 /** Number of possible configurations. */ 120 uint8_t configuration_count; 121 uint8_t reserved; 122 } __attribute__ ((packed)) usb_standard_device_qualifier_descriptor_t; 123 91 124 /** Standard USB configuration descriptor. 92 125 */ … … 116 149 } __attribute__ ((packed)) usb_standard_configuration_descriptor_t; 117 150 151 /** USB Other Speed Configuration descriptor shows values that would change 152 * in the configuration descriptor if the device operated at its other 153 * possible speed (HIGH vs. FULL) 154 */ 155 typedef usb_standard_configuration_descriptor_t 156 usb_other_speed_configuration_descriptor_t; 157 118 158 /** Standard USB interface descriptor. 119 159 */ … … 157 197 */ 158 198 uint8_t attributes; 159 /** Maximum packet size. */ 199 /** Maximum packet size. 200 * Lower 10 bits represent the actuall size 201 * Bits 11,12 specify addtional transfer opportunitities for 202 * HS INT and ISO transfers. */ 160 203 uint16_t max_packet_size; 204 #define ED_MPS_PACKET_SIZE_MASK 0x3ff 205 #define ED_MPS_PACKET_SIZE_GET(value) \ 206 ((value) & ED_MPS_PACKET_SIZE_MASK) 207 #define ED_MPS_TRANS_OPPORTUNITIES_GET(value) \ 208 ((((value) >> 10) & 0x3) + 1) 161 209 /** Polling interval in milliseconds. 162 210 * Ignored for bulk and control endpoints. -
uspace/lib/usb/include/usb/dev.h
r5b18137 rb4b534ac 36 36 37 37 #include <devman.h> 38 #include <usb/usb.h>39 38 40 int usb_get_info_by_handle(devman_handle_t, 41 devman_handle_t *, usb_address_t *, int *); 42 43 static inline int usb_get_hc_by_handle(devman_handle_t dev, devman_handle_t *hc) 44 { 45 return usb_get_info_by_handle(dev, hc, NULL, NULL); 46 } 47 48 static inline int usb_get_address_by_handle( 49 devman_handle_t dev, usb_address_t *address) 50 { 51 return usb_get_info_by_handle(dev, NULL, address, NULL); 52 } 53 54 static inline int usb_get_iface_by_handle(devman_handle_t dev, int *iface) 55 { 56 return usb_get_info_by_handle(dev, NULL, NULL, iface); 57 } 58 59 int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *, 60 devman_handle_t *); 39 int usb_resolve_device_handle(const char *, devman_handle_t *); 61 40 #endif 62 41 /** -
uspace/lib/usb/include/usb/usb.h
r5b18137 rb4b534ac 84 84 } usb_speed_t; 85 85 86 static inline bool usb_speed_is_11(const usb_speed_t s) 87 { 88 return (s == USB_SPEED_FULL) || (s == USB_SPEED_LOW); 89 } 90 86 91 const char *usb_str_speed(usb_speed_t); 87 92 … … 110 115 #define USB_ADDRESS_DEFAULT 0 111 116 /** Maximum address number in USB 1.1. */ 112 #define USB11_ADDRESS_MAX 128 117 #define USB11_ADDRESS_MAX 127 118 #define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1) 119 120 /** Check USB address for allowed values. 121 * 122 * @param ep USB address. 123 * @return True, if value is wihtin limits, false otherwise. 124 */ 125 static inline bool usb_address_is_valid(usb_address_t a) 126 { 127 return (a >= USB_ADDRESS_DEFAULT) && (a <= USB11_ADDRESS_MAX); 128 } 113 129 114 130 /** USB endpoint number type. … … 117 133 typedef int16_t usb_endpoint_t; 118 134 119 /** Maximum endpoint number in USB 1.1. 120 */ 135 /** Default control endpoint */ 136 #define USB_ENDPOINT_DEFAULT_CONTROL 0 137 /** Maximum endpoint number in USB 1.1. */ 121 138 #define USB11_ENDPOINT_MAX 16 139 140 /** Check USB endpoint for allowed values. 141 * 142 * @param ep USB endpoint number. 143 * @return True, if value is wihtin limits, false otherwise. 144 */ 145 static inline bool usb_endpoint_is_valid(usb_endpoint_t ep) 146 { 147 return (ep >= USB_ENDPOINT_DEFAULT_CONTROL) && 148 (ep < USB11_ENDPOINT_MAX); 149 } 122 150 123 151 … … 133 161 } usb_target_t; 134 162 163 135 164 /** Check USB target for allowed values (address and endpoint). 136 165 * … … 140 169 static inline bool usb_target_is_valid(usb_target_t target) 141 170 { 142 return !(target.endpoint > 15 || target.endpoint < 0143 || target.address >= USB11_ADDRESS_MAX || target.address < 0);171 return usb_address_is_valid(target.address) && 172 usb_endpoint_is_valid(target.endpoint); 144 173 } 145 174 -
uspace/lib/usb/src/class.c
r5b18137 rb4b534ac 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <errno.h>37 36 38 37 /** Tell string representation of USB class. -
uspace/lib/usb/src/debug.c
r5b18137 rb4b534ac 33 33 * Debugging and logging support. 34 34 */ 35 #include <adt/list.h>36 35 #include <fibril_synch.h> 37 #include <errno.h>38 #include <stdlib.h>39 #include <stdio.h>40 36 #include <ddf/log.h> 41 37 #include <usb/debug.h> -
uspace/lib/usb/src/dev.c
r5b18137 rb4b534ac 29 29 30 30 #include <usb/dev.h> 31 #include <usb/hc.h>32 31 #include <errno.h> 33 32 #include <usb_iface.h> 34 33 #include <str.h> 35 34 #include <stdio.h> 36 37 #define MAX_DEVICE_PATH 102438 39 /** Find host controller handle, address and iface number for the device.40 *41 * @param[in] device_handle Device devman handle.42 * @param[out] hc_handle Where to store handle of host controller43 * controlling device with @p device_handle handle.44 * @param[out] address Place to store the device's address45 * @param[out] iface Place to stoer the assigned USB interface number.46 * @return Error code.47 */48 int usb_get_info_by_handle(devman_handle_t device_handle,49 devman_handle_t *hc_handle, usb_address_t *address, int *iface)50 {51 async_sess_t *parent_sess =52 devman_parent_device_connect(device_handle, IPC_FLAG_BLOCKING);53 if (!parent_sess)54 return ENOMEM;55 56 async_exch_t *exch = async_exchange_begin(parent_sess);57 if (!exch) {58 async_hangup(parent_sess);59 return ENOMEM;60 }61 62 usb_address_t tmp_address;63 devman_handle_t tmp_handle;64 int tmp_iface;65 66 if (address) {67 const int ret = usb_get_my_address(exch, &tmp_address);68 if (ret != EOK) {69 async_exchange_end(exch);70 async_hangup(parent_sess);71 return ret;72 }73 }74 75 if (hc_handle) {76 const int ret = usb_get_hc_handle(exch, &tmp_handle);77 if (ret != EOK) {78 async_exchange_end(exch);79 async_hangup(parent_sess);80 return ret;81 }82 }83 84 if (iface) {85 const int ret = usb_get_my_interface(exch, &tmp_iface);86 switch (ret) {87 case ENOTSUP:88 /* Implementing GET_MY_INTERFACE is voluntary. */89 tmp_iface = -1;90 case EOK:91 break;92 default:93 async_exchange_end(exch);94 async_hangup(parent_sess);95 return ret;96 }97 }98 99 if (hc_handle)100 *hc_handle = tmp_handle;101 102 if (address)103 *address = tmp_address;104 105 if (iface)106 *iface = tmp_iface;107 108 async_exchange_end(exch);109 async_hangup(parent_sess);110 111 return EOK;112 }113 114 static bool try_parse_bus_and_address(const char *path,115 const char **func_start,116 devman_handle_t *out_hc_handle, usb_address_t *out_device_address)117 {118 uint64_t sid;119 size_t address;120 int rc;121 const char *ptr;122 123 rc = str_uint64_t(path, &ptr, 10, false, &sid);124 if (rc != EOK) {125 return false;126 }127 if ((*ptr == ':') || (*ptr == '.')) {128 ptr++;129 } else {130 return false;131 }132 rc = str_size_t(ptr, func_start, 10, false, &address);133 if (rc != EOK) {134 return false;135 }136 rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle);137 if (rc != EOK) {138 return false;139 }140 if (out_device_address != NULL) {141 *out_device_address = (usb_address_t) address;142 }143 return true;144 }145 146 static int get_device_handle_by_address(devman_handle_t hc_handle, int addr,147 devman_handle_t *dev_handle)148 {149 usb_hc_connection_t conn;150 usb_hc_connection_initialize(&conn, hc_handle);151 152 const int rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);153 154 return rc;155 }156 35 157 36 /** Resolve handle and address of USB device from its path. … … 174 53 * @return Error code. 175 54 */ 176 int usb_resolve_device_handle(const char *dev_path, devman_handle_t *out_hc_handle, 177 usb_address_t *out_dev_addr, devman_handle_t *out_dev_handle) 55 int usb_resolve_device_handle(const char *dev_path, devman_handle_t *dev_handle) 178 56 { 179 if (dev_path == NULL ) {57 if (dev_path == NULL || dev_handle == NULL) { 180 58 return EBADMEM; 181 59 } 182 60 183 bool found_hc = false; 184 bool found_addr = false; 185 devman_handle_t hc_handle, dev_handle; 186 usb_address_t dev_addr = -1; 187 int rc; 188 bool is_bus_addr; 189 const char *func_start = NULL; 190 char *path = NULL; 61 /* First, try to get the device handle. */ 62 int rc = devman_fun_get_handle(dev_path, dev_handle, 0); 191 63 192 /* First try the BUS.ADDR format. */ 193 is_bus_addr = try_parse_bus_and_address(dev_path, &func_start, 194 &hc_handle, &dev_addr); 195 if (is_bus_addr) { 196 found_hc = true; 197 found_addr = true; 198 /* 199 * Now get the handle of the device. We will need that 200 * in both cases. If there is only BUS.ADDR, it will 201 * be the handle to be returned to the caller, otherwise 202 * we will need it to resolve the path to which the 203 * suffix would be appended. 204 */ 205 /* If there is nothing behind the BUS.ADDR, we will 206 * get the device handle from the host controller. 207 * Otherwise, we will 208 */ 209 rc = get_device_handle_by_address(hc_handle, dev_addr, 210 &dev_handle); 211 if (rc != EOK) { 212 return rc; 213 } 214 if (str_length(func_start) > 0) { 215 char tmp_path[MAX_DEVICE_PATH]; 216 rc = devman_fun_get_path(dev_handle, 217 tmp_path, MAX_DEVICE_PATH); 218 if (rc != EOK) { 219 return rc; 220 } 221 rc = asprintf(&path, "%s%s", tmp_path, func_start); 222 if (rc < 0) { 223 return ENOMEM; 224 } 225 } else { 226 /* Everything is resolved. Get out of here. */ 227 goto copy_out; 228 } 229 } else { 230 path = str_dup(dev_path); 231 if (path == NULL) { 232 return ENOMEM; 233 } 64 /* Next, try parsing dev_handle from the provided string */ 65 if (rc != EOK) { 66 *dev_handle = strtoul(dev_path, NULL, 10); 67 //FIXME: check errno 68 rc = EOK; 234 69 } 235 236 /* First try to get the device handle. */ 237 rc = devman_fun_get_handle(path, &dev_handle, 0); 238 if (rc != EOK) { 239 free(path); 240 /* Invalid path altogether. */ 241 return rc; 242 } 243 244 /* Remove suffixes and hope that we will encounter device node. */ 245 while (str_length(path) > 0) { 246 /* Get device handle first. */ 247 devman_handle_t tmp_handle; 248 rc = devman_fun_get_handle(path, &tmp_handle, 0); 249 if (rc != EOK) { 250 free(path); 251 return rc; 252 } 253 254 /* Try to find its host controller. */ 255 if (!found_hc) { 256 rc = usb_get_hc_by_handle(tmp_handle, &hc_handle); 257 if (rc == EOK) { 258 found_hc = true; 259 } 260 } 261 262 /* Try to get its address. */ 263 if (!found_addr) { 264 rc = usb_get_address_by_handle(tmp_handle, &dev_addr); 265 if (rc == 0) { 266 found_addr = true; 267 } 268 } 269 270 /* Speed-up. */ 271 if (found_hc && found_addr) { 272 break; 273 } 274 275 /* Remove the last suffix. */ 276 char *slash_pos = str_rchr(path, '/'); 277 if (slash_pos != NULL) { 278 *slash_pos = 0; 279 } 280 } 281 282 free(path); 283 284 if (!found_addr || !found_hc) { 285 return ENOENT; 286 } 287 288 copy_out: 289 if (out_dev_addr != NULL) { 290 *out_dev_addr = dev_addr; 291 } 292 if (out_hc_handle != NULL) { 293 *out_hc_handle = hc_handle; 294 } 295 if (out_dev_handle != NULL) { 296 *out_dev_handle = dev_handle; 297 } 298 299 return EOK; 70 return rc; 300 71 } -
uspace/lib/usb/src/dump.c
r5b18137 rb4b534ac 33 33 * Descriptor dumping. 34 34 */ 35 #include <adt/list.h>36 #include <fibril_synch.h>37 #include <errno.h>38 35 #include <stdlib.h> 39 36 #include <stdio.h> … … 41 38 #include <usb/descriptor.h> 42 39 #include <usb/classes/classes.h> 40 #include <usb/classes/hub.h> 41 #include <usb/usb.h> 43 42 44 43 /** Mapping between descriptor id and dumping function. */ … … 276 275 const uint8_t *descriptor, size_t descriptor_length) 277 276 { 278 /* TODO */ 277 usb_hub_descriptor_header_t *d = 278 (usb_hub_descriptor_header_t *) descriptor; 279 if (descriptor_length < sizeof(d)) 280 return; 281 282 PRINTLINE("bDescLength: = %d", d->length); 283 PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type); 284 PRINTLINE("bNbrPorts = %d", d->port_count); 285 PRINTLINE("bHubCharacteristics = 0x%02x%02x (%s;%s%s)", 286 d->characteristics_reserved, d->characteristics, 287 (d->characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG) ? 288 "No Power Switching" : 289 ((d->characteristics & HUB_CHAR_POWER_PER_PORT_FLAG) ? 290 "Per-Port Switching" : "Ganged Power Switching"), 291 (d->characteristics & HUB_CHAR_COMPOUND_DEVICE) ? 292 "Compound Device;" : "", 293 (d->characteristics & HUB_CHAR_NO_OC_FLAG) ? 294 "No OC Protection" : 295 ((d->characteristics & HUB_CHAR_OC_PER_PORT_FLAG) ? 296 "Individual Port OC Protection" : 297 "Global OC Protection") 298 ); 299 PRINTLINE("bPwrOn2PwrGood = %d (%d ms)", 300 d->power_good_time, d->power_good_time * 2); 301 PRINTLINE("bHubContrCurrent = %d (%d mA)", 302 d->max_current, d->max_current); 303 const size_t port_bytes = (descriptor_length - sizeof(*d)) / 2; 304 const uint8_t *removable_mask = descriptor + sizeof(*d); 305 const uint8_t *powered_mask = descriptor + sizeof(*d) + port_bytes; 306 307 if (port_bytes == 0 308 || port_bytes > (((d->port_count / (unsigned)8) + 1) * 2)) { 309 PRINTLINE("::CORRUPTED DESCRIPTOR:: (%zu bytes remain)", 310 port_bytes * 2); 311 } 312 313 fprintf(output, "%sDeviceRemovable = 0x", 314 line_prefix ? line_prefix : " - "); 315 for (unsigned i = port_bytes; i > 0; --i) 316 fprintf(output, "%02x", removable_mask[i - 1]); 317 fprintf(output, " (0b1 - Device non-removable)%s", 318 line_suffix ? line_suffix : "\n"); 319 320 fprintf(output, "%sPortPwrCtrlMask = 0x", 321 line_prefix ? line_prefix : " - "); 322 for (unsigned i = port_bytes; i > 0; --i) 323 fprintf(output, "%02x", powered_mask[i - 1]); 324 fprintf(output, " (Legacy - All should be 0b1)%s", 325 line_suffix ? line_suffix : "\n"); 279 326 } 280 327 -
uspace/lib/usb/src/usb.c
r5b18137 rb4b534ac 34 34 */ 35 35 #include <usb/usb.h> 36 #include < errno.h>36 #include <usb/request.h> 37 37 38 #define ARR_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) 38 #include <assert.h> 39 #include <byteorder.h> 40 #include <macros.h> 39 41 40 42 static const char *str_speed[] = { … … 71 73 const char *usb_str_transfer_type(usb_transfer_type_t t) 72 74 { 73 if (t >= ARR _SIZE(str_transfer_type)) {75 if (t >= ARRAY_SIZE(str_transfer_type)) { 74 76 return "invalid"; 75 77 } … … 84 86 const char *usb_str_transfer_type_short(usb_transfer_type_t t) 85 87 { 86 if (t >= ARR _SIZE(str_transfer_type_short)) {88 if (t >= ARRAY_SIZE(str_transfer_type_short)) { 87 89 return "invl"; 88 90 } … … 97 99 const char *usb_str_direction(usb_direction_t d) 98 100 { 99 if (d >= ARR _SIZE(str_direction)) {101 if (d >= ARRAY_SIZE(str_direction)) { 100 102 return "invalid"; 101 103 } … … 110 112 const char *usb_str_speed(usb_speed_t s) 111 113 { 112 if (s >= ARR _SIZE(str_speed)) {114 if (s >= ARRAY_SIZE(str_speed)) { 113 115 return "invalid"; 114 116 } … … 116 118 } 117 119 120 /** Check setup packet data for signs of toggle reset. 121 * 122 * @param[in] requst Setup requst data. 123 * @retval -1 No endpoints need reset. 124 * @retval 0 All endpoints need reset. 125 * @retval >0 Specified endpoint needs reset. 126 */ 127 int usb_request_needs_toggle_reset( 128 const usb_device_request_setup_packet_t *request) 129 { 130 assert(request); 131 switch (request->request) 132 { 133 /* Clear Feature ENPOINT_STALL */ 134 case USB_DEVREQ_CLEAR_FEATURE: /*resets only cleared ep */ 135 /* 0x2 ( HOST to device | STANDART | TO ENPOINT) */ 136 if ((request->request_type == 0x2) && 137 (request->value == USB_FEATURE_ENDPOINT_HALT)) 138 return uint16_usb2host(request->index); 139 break; 140 case USB_DEVREQ_SET_CONFIGURATION: 141 case USB_DEVREQ_SET_INTERFACE: 142 /* Recipient must be device, this resets all endpoints, 143 * In fact there should be no endpoints but EP 0 registered 144 * as different interfaces use different endpoints, 145 * unless you're changing configuration or alternative 146 * interface of an already setup device. */ 147 if (!(request->request_type & SETUP_REQUEST_TYPE_DEVICE_TO_HOST)) 148 return 0; 149 break; 150 default: 151 break; 152 } 153 return -1; 154 } 155 118 156 /** 119 157 * @} -
uspace/lib/usbdev/Makefile
r5b18137 rb4b534ac 36 36 SOURCES = \ 37 37 src/altiface.c \ 38 src/driver.c \ 38 39 src/devdrv.c \ 39 40 src/devpoll.c \ 40 41 src/dp.c \ 41 src/hub.c \42 42 src/pipes.c \ 43 43 src/pipesinit.c \ -
uspace/lib/usbdev/include/usb/dev/alternate_ifaces.h
r5b18137 rb4b534ac 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2013 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 31 32 */ 32 33 /** @file 33 * Functions needed by hub drivers. 34 * 35 * For class specific requests, see usb/classes/hub.h. 34 * USB device driver framework. 36 35 */ 37 36 38 #ifndef LIBUSBDEV_ HUB_H_39 #define LIBUSBDEV_ HUB_H_37 #ifndef LIBUSBDEV_ALTERNATE_IFACES_H_ 38 #define LIBUSBDEV_ALTERNATE_IFACES_H_ 40 39 41 #include < ddf/driver.h>40 #include <usb/descriptor.h> 42 41 #include <sys/types.h> 43 #include <errno.h>44 #include <usb/hc.h>45 42 46 extern int usb_hc_new_device_wrapper(ddf_dev_t *, ddf_fun_t *, 47 usb_hc_connection_t *, usb_speed_t, int (*)(void *), void *, 48 usb_address_t *, ddf_dev_ops_t *); 49 50 /** Info about device attached to host controller. 51 * 52 * This structure exists only to keep the same signature of 53 * usb_hc_register_device() when more properties of the device 54 * would have to be passed to the host controller. 43 /** Wrapper for data related to alternate interface setting. 44 * The pointers will typically point inside configuration descriptor and 45 * thus you shall not deallocate them. 55 46 */ 56 47 typedef struct { 57 /** Device address. */ 58 usb_address_t address; 59 /** DDF function (external) of the device. */ 60 ddf_fun_t *fun; 61 } usb_hub_attached_device_t; 48 /** Interface descriptor. */ 49 const usb_standard_interface_descriptor_t *interface; 50 /** Pointer to start of descriptor tree bound with this interface. */ 51 const uint8_t *nested_descriptors; 52 /** Size of data pointed by nested_descriptors in bytes. */ 53 size_t nested_descriptors_size; 54 } usb_alternate_interface_descriptors_t; 62 55 63 extern int usb_hub_register_device(usb_hc_connection_t *, 64 const usb_hub_attached_device_t *); 56 /** Alternate interface settings. */ 57 typedef struct { 58 /** Array of alternate interfaces descriptions. */ 59 const usb_alternate_interface_descriptors_t *alternatives; 60 /** Size of @c alternatives array. */ 61 size_t alternative_count; 62 /** Index of currently selected one. */ 63 size_t current; 64 } usb_alternate_interfaces_t; 65 65 66 static inline int usb_hub_unregister_device(usb_hc_connection_t *conn, 67 const usb_hub_attached_device_t *attached_device) 68 { 69 assert(conn); 70 if (attached_device == NULL) 71 return EBADMEM; 72 73 return usb_hc_release_address(conn, attached_device->address); 74 } 66 size_t usb_interface_count_alternates(const uint8_t *, size_t, uint8_t); 67 int usb_alternate_interfaces_init(usb_alternate_interfaces_t *, 68 const uint8_t *, size_t, int); 69 void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *); 75 70 76 71 #endif 77 78 72 /** 79 73 * @} -
uspace/lib/usbdev/include/usb/dev/dp.h
r5b18137 rb4b534ac 37 37 38 38 #include <sys/types.h> 39 #include <usb/usb.h>40 #include <usb/descriptor.h>41 39 42 40 /** USB descriptors nesting. … … 79 77 const usb_dp_parser_data_t *, const uint8_t *, const uint8_t *); 80 78 81 void usb_dp_walk_simple( uint8_t *, size_t, const usb_dp_descriptor_nesting_t *,82 walk_callback_t, void *);79 void usb_dp_walk_simple(const uint8_t *, size_t, 80 const usb_dp_descriptor_nesting_t *, walk_callback_t, void *); 83 81 84 82 #endif -
uspace/lib/usbdev/include/usb/dev/driver.h
r5b18137 rb4b534ac 37 37 #define LIBUSBDEV_DRIVER_H_ 38 38 39 #include <usb/hc.h> 40 #include <usb/dev/usb_device_connection.h> 39 #include <usb/dev/device.h> 41 40 #include <usb/dev/pipes.h> 42 43 /** Descriptors for USB device. */44 typedef struct {45 /** Standard device descriptor. */46 usb_standard_device_descriptor_t device;47 /** Full configuration descriptor of current configuration. */48 const uint8_t *configuration;49 size_t configuration_size;50 } usb_device_descriptors_t;51 52 /** Wrapper for data related to alternate interface setting.53 * The pointers will typically point inside configuration descriptor and54 * thus you shall not deallocate them.55 */56 typedef struct {57 /** Interface descriptor. */58 const usb_standard_interface_descriptor_t *interface;59 /** Pointer to start of descriptor tree bound with this interface. */60 const uint8_t *nested_descriptors;61 /** Size of data pointed by nested_descriptors in bytes. */62 size_t nested_descriptors_size;63 } usb_alternate_interface_descriptors_t;64 65 /** Alternate interface settings. */66 typedef struct {67 /** Array of alternate interfaces descriptions. */68 usb_alternate_interface_descriptors_t *alternatives;69 /** Size of @c alternatives array. */70 size_t alternative_count;71 /** Index of currently selected one. */72 size_t current;73 } usb_alternate_interfaces_t;74 75 /** USB device structure. */76 typedef struct {77 /** Connection to USB hc, used by wire and arbitrary requests. */78 usb_hc_connection_t hc_conn;79 /** Connection backing the pipes.80 * Typically, you will not need to use this attribute at all.81 */82 usb_device_connection_t wire;83 /** The default control pipe. */84 usb_pipe_t ctrl_pipe;85 /** Other endpoint pipes.86 * This is an array of other endpoint pipes in the same order as87 * in usb_driver_t.88 */89 usb_endpoint_mapping_t *pipes;90 /** Number of other endpoint pipes. */91 size_t pipes_count;92 /** Current interface.93 * Usually, drivers operate on single interface only.94 * This item contains the value of the interface or -1 for any.95 */96 int interface_no;97 98 /** Alternative interfaces. */99 usb_alternate_interfaces_t alternate_interfaces;100 101 /** Some useful descriptors. */102 usb_device_descriptors_t descriptors;103 104 /** Generic DDF device backing this one. DO NOT TOUCH! */105 ddf_dev_t *ddf_dev;106 /** Custom driver data.107 * Do not use the entry in generic device, that is already used108 * by the framework.109 */110 void *driver_data;111 } usb_device_t;112 41 113 42 /** USB driver ops. */ … … 164 93 int usb_driver_main(const usb_driver_t *); 165 94 166 int usb_device_init(usb_device_t *, ddf_dev_t *,167 const usb_endpoint_description_t **, const char **);168 void usb_device_deinit(usb_device_t *);169 170 int usb_device_select_interface(usb_device_t *, uint8_t,171 const usb_endpoint_description_t **);172 173 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);174 void usb_device_release_descriptors(usb_device_descriptors_t *);175 176 int usb_device_create_pipes(usb_device_connection_t *,177 const usb_endpoint_description_t **, const uint8_t *, size_t, int, int,178 usb_endpoint_mapping_t **, size_t *);179 void usb_device_destroy_pipes(usb_endpoint_mapping_t *, size_t);180 181 void * usb_device_data_alloc(usb_device_t *, size_t);182 183 size_t usb_interface_count_alternates(const uint8_t *, size_t, uint8_t);184 int usb_alternate_interfaces_init(usb_alternate_interfaces_t *,185 const uint8_t *, size_t, int);186 void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *);187 95 #endif 188 96 /** -
uspace/lib/usbdev/include/usb/dev/pipes.h
r5b18137 rb4b534ac 35 35 #define LIBUSBDEV_PIPES_H_ 36 36 37 #include <sys/types.h>38 #include <ipc/devman.h>39 #include <ddf/driver.h>40 #include <fibril_synch.h>41 37 #include <usb/usb.h> 42 38 #include <usb/descriptor.h> 43 #include <usb/dev/usb_device_connection.h> 39 #include <usb_iface.h> 40 41 #include <stdbool.h> 42 #include <sys/types.h> 44 43 45 44 #define CTRL_PIPE_MIN_PACKET_SIZE 8 … … 50 49 */ 51 50 typedef struct { 52 /** The connection used for sending the data. */53 usb_device_connection_t *wire;54 55 51 /** Endpoint number. */ 56 52 usb_endpoint_t endpoint_no; … … 65 61 size_t max_packet_size; 66 62 63 /** Number of packets per frame/uframe. 64 * Only valid for HS INT and ISO transfers. All others should set to 1*/ 65 unsigned packets; 66 67 67 /** Whether to automatically reset halt on the endpoint. 68 68 * Valid only for control endpoint zero. 69 69 */ 70 70 bool auto_reset_halt; 71 72 /** The connection used for sending the data. */ 73 usb_dev_session_t *bus_session; 71 74 } usb_pipe_t; 72 75 … … 105 108 } usb_endpoint_mapping_t; 106 109 107 int usb_pipe_initialize(usb_pipe_t *, usb_device_connection_t *, 108 usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t); 109 int usb_pipe_initialize_default_control(usb_pipe_t *, 110 usb_device_connection_t *); 110 int usb_pipe_initialize(usb_pipe_t *, usb_endpoint_t, usb_transfer_type_t, 111 size_t, usb_direction_t, unsigned, usb_dev_session_t *); 112 int usb_pipe_initialize_default_control(usb_pipe_t *, usb_dev_session_t *); 111 113 112 114 int usb_pipe_probe_default_control(usb_pipe_t *); 113 115 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 114 size_t, const uint8_t *, size_t, usb_dev ice_connection_t *);116 size_t, const uint8_t *, size_t, usb_dev_session_t *); 115 117 116 118 int usb_pipe_register(usb_pipe_t *, unsigned); 117 119 int usb_pipe_unregister(usb_pipe_t *); 118 119 int usb_pipe_start_long_transfer(usb_pipe_t *);120 int usb_pipe_end_long_transfer(usb_pipe_t *);121 120 122 121 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usbdev/include/usb/dev/poll.h
r5b18137 rb4b534ac 36 36 #define LIBUSBDEV_POLL_H_ 37 37 38 #include <usb/dev/driver.h> 39 #include <time.h> 38 #include <usb/usb.h> 39 #include <usb/dev/device.h> 40 #include <usb/dev/pipes.h> 41 42 #include <stdbool.h> 43 #include <sys/types.h> 40 44 41 45 /** Parameters and callbacks for automated polling. */ … … 87 91 } usb_device_auto_polling_t; 88 92 89 int usb_device_auto_polling(usb_device_t *, size_t, 93 typedef bool (*usb_polling_callback_t)(usb_device_t *, uint8_t *, size_t, void *); 94 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *); 95 96 int usb_device_auto_polling(usb_device_t *, usb_endpoint_t, 90 97 const usb_device_auto_polling_t *, size_t); 91 98 92 typedef bool (*usb_polling_callback_t)(usb_device_t *, 93 uint8_t *, size_t, void *); 94 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *); 99 int usb_device_auto_poll(usb_device_t *, usb_endpoint_t, 100 usb_polling_callback_t, size_t, int, usb_polling_terminted_callback_t, void *); 95 101 96 int usb_device_auto_poll(usb_device_t *, size_t, 97 usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *); 102 int usb_device_auto_polling_desc(usb_device_t *, 103 const usb_endpoint_description_t *, const usb_device_auto_polling_t *, 104 size_t); 105 106 int usb_device_auto_poll_desc(usb_device_t *, 107 const usb_endpoint_description_t *, usb_polling_callback_t, size_t, int, 108 usb_polling_terminted_callback_t, void *); 98 109 99 110 #endif -
uspace/lib/usbdev/include/usb/dev/recognise.h
r5b18137 rb4b534ac 37 37 #define LIBUSBDEV_RECOGNISE_H_ 38 38 39 #include <sys/types.h> 40 #include <usb/usb.h> 39 #include <usb/descriptor.h> 41 40 #include <usb/dev/pipes.h> 42 #include <ipc/devman.h> 41 42 #include <devman.h> 43 43 44 44 extern int usb_device_create_match_ids_from_device_descriptor( … … 50 50 51 51 extern int usb_device_create_match_ids(usb_pipe_t *, match_id_list_t *); 52 53 extern int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,54 ddf_dev_t *, ddf_fun_t *, ddf_dev_ops_t *);55 56 52 #endif 57 53 -
uspace/lib/usbdev/include/usb/dev/request.h
r5b18137 rb4b534ac 41 41 #include <usb/dev/pipes.h> 42 42 #include <usb/descriptor.h> 43 44 /** USB device status - device is self powered (opposed to bus powered). */ 45 #define USB_DEVICE_STATUS_SELF_POWERED ((uint16_t)(1 << 0)) 46 47 /** USB device status - remote wake-up signaling is enabled. */ 48 #define USB_DEVICE_STATUS_REMOTE_WAKEUP ((uint16_t)(1 << 1)) 49 50 /** USB endpoint status - endpoint is halted (stalled). */ 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) 58 59 /** Standard device request. */ 60 typedef enum { 61 USB_DEVREQ_GET_STATUS = 0, 62 USB_DEVREQ_CLEAR_FEATURE = 1, 63 USB_DEVREQ_SET_FEATURE = 3, 64 USB_DEVREQ_SET_ADDRESS = 5, 65 USB_DEVREQ_GET_DESCRIPTOR = 6, 66 USB_DEVREQ_SET_DESCRIPTOR = 7, 67 USB_DEVREQ_GET_CONFIGURATION = 8, 68 USB_DEVREQ_SET_CONFIGURATION = 9, 69 USB_DEVREQ_GET_INTERFACE = 10, 70 USB_DEVREQ_SET_INTERFACE = 11, 71 USB_DEVREQ_SYNCH_FRAME = 12, 72 USB_DEVREQ_LAST_STD 73 } usb_stddevreq_t; 74 75 /** Device request setup packet. 76 * The setup packet describes the request. 77 */ 78 typedef struct { 79 /** Request type. 80 * The type combines transfer direction, request type and 81 * intended recipient. 82 */ 83 uint8_t request_type; 84 #define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7) 85 #define SETUP_REQUEST_TYPE_GET_TYPE(rt) ((rt >> 5) & 0x3) 86 #define SETUP_REQUEST_TYPE_GET_RECIPIENT(rec) (rec & 0x1f) 87 #define SETUP_REQUEST_TO_HOST(type, recipient) \ 88 (uint8_t)((1 << 7) | ((type & 0x3) << 5) | (recipient & 0x1f)) 89 #define SETUP_REQUEST_TO_DEVICE(type, recipient) \ 90 (uint8_t)(((type & 0x3) << 5) | (recipient & 0x1f)) 91 92 /** Request identification. */ 93 uint8_t request; 94 /** Main parameter to the request. */ 95 union __attribute__ ((packed)) { 96 uint16_t value; 97 /* FIXME: add #ifdefs according to host endianness */ 98 struct __attribute__ ((packed)) { 99 uint8_t value_low; 100 uint8_t value_high; 101 }; 102 }; 103 /** Auxiliary parameter to the request. 104 * Typically, it is offset to something. 105 */ 106 uint16_t index; 107 /** Length of extra data. */ 108 uint16_t length; 109 } __attribute__ ((packed)) usb_device_request_setup_packet_t; 43 #include <usb/request.h> 110 44 111 45 int usb_control_request_set(usb_pipe_t *, 112 46 usb_request_type_t, usb_request_recipient_t, uint8_t, 113 uint16_t, uint16_t, void *, size_t);47 uint16_t, uint16_t, const void *, size_t); 114 48 115 49 int usb_control_request_get(usb_pipe_t *, … … 135 69 void *, size_t, size_t *); 136 70 int usb_request_get_full_configuration_descriptor_alloc(usb_pipe_t *, 137 int, void **, size_t *);71 int, const void **, size_t *); 138 72 int usb_request_set_descriptor(usb_pipe_t *, usb_request_type_t, 139 usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t);73 usb_request_recipient_t, uint8_t, uint8_t, uint16_t, const void *, size_t); 140 74 141 75 int usb_request_get_configuration(usb_pipe_t *, uint8_t *); 142 76 int usb_request_set_configuration(usb_pipe_t *, uint8_t); 77 143 78 int usb_request_get_interface(usb_pipe_t *, uint8_t, uint8_t *); 144 79 int usb_request_set_interface(usb_pipe_t *, uint8_t, uint8_t); -
uspace/lib/usbdev/src/altiface.c
r5b18137 rb4b534ac 34 34 */ 35 35 36 #include <usb/dev/driver.h> 37 #include <usb/dev/request.h> 38 #include <usb/debug.h> 36 #include <usb/dev/alternate_ifaces.h> 39 37 #include <usb/dev/dp.h> 38 #include <assert.h> 40 39 #include <errno.h> 41 #include <str_error.h> 42 #include <assert.h> 40 #include <stdlib.h> 43 41 44 42 /** Count number of alternate settings of a interface. … … 105 103 } 106 104 107 alternates->alternative_count 108 = usb_interface_count_alternates(config_descr, config_descr_size, 109 interface_number); 105 const size_t alt_count = usb_interface_count_alternates(config_descr, 106 config_descr_size, interface_number); 110 107 111 if (alt ernates->alternative_count == 0) {108 if (alt_count == 0) { 112 109 return ENOENT; 113 110 } 114 111 115 alternates->alternatives = calloc(alternates->alternative_count,112 usb_alternate_interface_descriptors_t *alts = calloc(alt_count, 116 113 sizeof(usb_alternate_interface_descriptors_t)); 117 if (alt ernates->alternatives == NULL) {114 if (alts == NULL) { 118 115 return ENOMEM; 119 116 } … … 128 125 }; 129 126 130 usb_alternate_interface_descriptors_t *iterator131 = &alternates->alternatives[0];132 133 const usb_alternate_interface_descriptors_t *end134 = &alternates->alternatives[alternates->alternative_count];135 127 136 128 const void *iface_ptr = 137 129 usb_dp_get_nested_descriptor(&dp_parser, &dp_data, dp_data.data); 138 130 139 while (iface_ptr != NULL && iterator < end) { 131 usb_alternate_interface_descriptors_t *iterator = alts; 132 for (; iface_ptr != NULL && iterator < &alts[alt_count]; ++iterator) { 140 133 const usb_standard_interface_descriptor_t *iface = iface_ptr; 141 134 … … 159 152 dp_data.data + dp_data.size : iface_ptr; 160 153 161 iterator->nested_descriptors_size 162 = next - iterator->nested_descriptors; 154 iterator->nested_descriptors_size = 155 next - iterator->nested_descriptors; 156 } 163 157 164 ++iterator;165 }158 alternates->alternatives = alts; 159 alternates->alternative_count = alt_count; 166 160 167 161 return EOK; -
uspace/lib/usbdev/src/devdrv.c
r5b18137 rb4b534ac 33 33 * USB device driver framework. 34 34 */ 35 #include <usb/dev/driver.h> 35 36 #include <usb_iface.h> 37 #include <usb/dev/alternate_ifaces.h> 38 #include <usb/dev/device.h> 39 #include <usb/dev/pipes.h> 36 40 #include <usb/dev/request.h> 37 41 #include <usb/debug.h> 38 #include <usb/dev.h> 42 #include <usb/descriptor.h> 43 #include <usb/usb.h> 44 45 #include <assert.h> 46 #include <async.h> 47 #include <devman.h> 39 48 #include <errno.h> 40 #include <str_error.h> 41 #include <assert.h> 42 43 static int generic_device_add(ddf_dev_t *); 44 static int generic_device_remove(ddf_dev_t *); 45 static int generic_device_gone(ddf_dev_t *); 46 47 static driver_ops_t generic_driver_ops = { 48 .dev_add = generic_device_add, 49 .dev_remove = generic_device_remove, 50 .dev_gone = generic_device_gone, 51 }; 52 static driver_t generic_driver = { 53 .driver_ops = &generic_driver_ops 54 }; 55 56 static const usb_driver_t *driver = NULL; 57 58 /** Main routine of USB device driver. 59 * 60 * Under normal conditions, this function never returns. 61 * 62 * @param drv USB device driver structure. 63 * @return Task exit status. 64 */ 65 int usb_driver_main(const usb_driver_t *drv) 66 { 67 assert(drv != NULL); 68 69 /* Prepare the generic driver. */ 70 generic_driver.name = drv->name; 71 72 driver = drv; 73 74 return ddf_driver_main(&generic_driver); 75 } 49 #include <stdlib.h> 50 51 #include <ddf/driver.h> 52 53 /** USB device structure. */ 54 typedef struct usb_device { 55 /** Connection to device on USB bus */ 56 usb_dev_session_t *bus_session; 57 /** devman handle */ 58 devman_handle_t handle; 59 /** The default control pipe. */ 60 usb_pipe_t ctrl_pipe; 61 62 /** Other endpoint pipes. 63 * This is an array of other endpoint pipes in the same order as 64 * in usb_driver_t. 65 */ 66 usb_endpoint_mapping_t *pipes; 67 /** Number of other endpoint pipes. */ 68 size_t pipes_count; 69 /** Current interface. 70 * Usually, drivers operate on single interface only. 71 * This item contains the value of the interface or -1 for any. 72 */ 73 int interface_no; 74 /** Alternative interfaces. */ 75 usb_alternate_interfaces_t alternate_interfaces; 76 /** Some useful descriptors for USB device. */ 77 usb_device_descriptors_t descriptors; 78 /** Generic DDF device backing this one. DO NOT TOUCH! */ 79 ddf_dev_t *ddf_dev; 80 /** Custom driver data. 81 * Do not use the entry in generic device, that is already used 82 * by the framework. 83 */ 84 void *driver_data; 85 86 } usb_device_t; 76 87 77 88 /** Count number of pipes the driver expects. … … 80 91 * @return Number of pipes (excluding default control pipe). 81 92 */ 82 static inline size_t count_other_pipes( 83 const usb_endpoint_description_t **endpoints) 93 static inline size_t count_pipes(const usb_endpoint_description_t **endpoints) 84 94 { 85 95 size_t count; 86 96 for (count = 0; endpoints != NULL && endpoints[count] != NULL; ++count); 87 97 return count; 88 }89 90 /** Callback when a new device is supposed to be controlled by this driver.91 *92 * This callback is a wrapper for USB specific version of @c device_add.93 *94 * @param gen_dev Device structure as prepared by DDF.95 * @return Error code.96 */97 int generic_device_add(ddf_dev_t *gen_dev)98 {99 assert(driver);100 assert(driver->ops);101 assert(driver->ops->device_add);102 103 /* Get place for driver data. */104 usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t));105 if (dev == NULL) {106 usb_log_error("USB device `%s' structure allocation failed.\n",107 ddf_dev_get_name(gen_dev));108 return ENOMEM;109 }110 111 /* Initialize generic USB driver data. */112 const char *err_msg = NULL;113 int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);114 if (rc != EOK) {115 usb_log_error("USB device `%s' init failed (%s): %s.\n",116 ddf_dev_get_name(gen_dev), err_msg, str_error(rc));117 return rc;118 }119 120 /* Start USB driver specific initialization. */121 rc = driver->ops->device_add(dev);122 if (rc != EOK)123 usb_device_deinit(dev);124 return rc;125 }126 127 /** Callback when a device is supposed to be removed from the system.128 *129 * This callback is a wrapper for USB specific version of @c device_remove.130 *131 * @param gen_dev Device structure as prepared by DDF.132 * @return Error code.133 */134 int generic_device_remove(ddf_dev_t *gen_dev)135 {136 assert(driver);137 assert(driver->ops);138 if (driver->ops->device_rem == NULL)139 return ENOTSUP;140 /* Just tell the driver to stop whatever it is doing */141 usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);142 const int ret = driver->ops->device_rem(usb_dev);143 if (ret != EOK)144 return ret;145 usb_device_deinit(usb_dev);146 return EOK;147 }148 149 /** Callback when a device was removed from the system.150 *151 * This callback is a wrapper for USB specific version of @c device_gone.152 *153 * @param gen_dev Device structure as prepared by DDF.154 * @return Error code.155 */156 int generic_device_gone(ddf_dev_t *gen_dev)157 {158 assert(driver);159 assert(driver->ops);160 if (driver->ops->device_gone == NULL)161 return ENOTSUP;162 usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);163 const int ret = driver->ops->device_gone(usb_dev);164 if (ret == EOK)165 usb_device_deinit(usb_dev);166 167 return ret;168 }169 170 /** Destroy existing pipes of a USB device.171 *172 * @param dev Device where to destroy the pipes.173 */174 static void destroy_current_pipes(usb_device_t *dev)175 {176 usb_device_destroy_pipes(dev->pipes, dev->pipes_count);177 dev->pipes = NULL;178 dev->pipes_count = 0;179 98 } 180 99 … … 201 120 * @return Error code. 202 121 */ 203 int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting, 204 const usb_endpoint_description_t **endpoints) 205 { 206 if (dev->interface_no < 0) { 122 int usb_device_select_interface(usb_device_t *usb_dev, 123 uint8_t alternate_setting, const usb_endpoint_description_t **endpoints) 124 { 125 assert(usb_dev); 126 127 if (usb_dev->interface_no < 0) { 207 128 return EINVAL; 208 129 } 209 130 210 /* Destroy existing pipes. */211 destroy_current_pipes(dev);212 213 131 /* Change the interface itself. */ 214 int rc = usb_request_set_interface(& dev->ctrl_pipe, dev->interface_no,215 alternate_setting);132 int rc = usb_request_set_interface(&usb_dev->ctrl_pipe, 133 usb_dev->interface_no, alternate_setting); 216 134 if (rc != EOK) { 217 135 return rc; 218 136 } 219 137 138 /* Change current alternative */ 139 usb_dev->alternate_interfaces.current = alternate_setting; 140 141 /* Destroy existing pipes. */ 142 usb_device_destroy_pipes(usb_dev); 143 220 144 /* Create new pipes. */ 221 rc = usb_device_create_pipes(&dev->wire, endpoints, 222 dev->descriptors.configuration, dev->descriptors.configuration_size, 223 dev->interface_no, (int)alternate_setting, 224 &dev->pipes, &dev->pipes_count); 145 rc = usb_device_create_pipes(usb_dev, endpoints); 225 146 226 147 return rc; … … 233 154 * @return Error code. 234 155 */ 235 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe, 236 usb_device_descriptors_t *descriptors) 237 { 238 assert(descriptors != NULL); 239 240 descriptors->configuration = NULL; 241 242 int rc; 243 244 /* It is worth to start a long transfer. */ 245 usb_pipe_start_long_transfer(ctrl_pipe); 156 static int usb_device_retrieve_descriptors(usb_device_t *usb_dev) 157 { 158 assert(usb_dev); 159 assert(usb_dev->descriptors.full_config == NULL); 246 160 247 161 /* Get the device descriptor. */ 248 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 162 int rc = usb_request_get_device_descriptor(&usb_dev->ctrl_pipe, 163 &usb_dev->descriptors.device); 249 164 if (rc != EOK) { 250 goto leave;165 return rc; 251 166 } 252 167 253 168 /* Get the full configuration descriptor. */ 254 169 rc = usb_request_get_full_configuration_descriptor_alloc( 255 ctrl_pipe, 0, (void **) &descriptors->configuration, 256 &descriptors->configuration_size); 257 258 leave: 259 usb_pipe_end_long_transfer(ctrl_pipe); 170 &usb_dev->ctrl_pipe, 0, 171 &usb_dev->descriptors.full_config, 172 &usb_dev->descriptors.full_config_size); 173 260 174 261 175 return rc; … … 266 180 * @param[in] descriptors Where to store the descriptors. 267 181 */ 268 void usb_device_release_descriptors(usb_device_descriptors_t *descriptors) 269 { 270 assert(descriptors); 271 free(descriptors->configuration); 272 descriptors->configuration = NULL; 182 static void usb_device_release_descriptors(usb_device_t *usb_dev) 183 { 184 assert(usb_dev); 185 free(usb_dev->descriptors.full_config); 186 usb_dev->descriptors.full_config = NULL; 187 usb_dev->descriptors.full_config_size = 0; 273 188 } 274 189 … … 280 195 * - registers endpoints with the host controller 281 196 * 282 * @param[in] wire Initialized backing connection to the host controller.283 197 * @param[in] endpoints Endpoints description, NULL terminated. 284 198 * @param[in] config_descr Configuration descriptor of active configuration. … … 292 206 * @return Error code. 293 207 */ 294 int usb_device_create_pipes(usb_device_connection_t *wire, 295 const usb_endpoint_description_t **endpoints, 296 const uint8_t *config_descr, size_t config_descr_size, 297 int interface_no, int interface_setting, 298 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) 299 { 300 assert(wire != NULL); 301 assert(config_descr != NULL); 302 assert(config_descr_size > 0); 303 assert(pipes_ptr != NULL); 304 305 size_t i; 306 int rc; 307 308 const size_t pipe_count = count_other_pipes(endpoints); 208 int usb_device_create_pipes(usb_device_t *usb_dev, 209 const usb_endpoint_description_t **endpoints) 210 { 211 assert(usb_dev); 212 assert(usb_dev->descriptors.full_config); 213 assert(usb_dev->pipes == NULL); 214 assert(usb_dev->pipes_count == 0); 215 216 size_t pipe_count = count_pipes(endpoints); 309 217 if (pipe_count == 0) { 310 if (pipes_count_ptr)311 *pipes_count_ptr = pipe_count;312 *pipes_ptr = NULL;313 218 return EOK; 314 219 } 315 220 316 usb_endpoint_mapping_t *pipes 317 =calloc(pipe_count, sizeof(usb_endpoint_mapping_t));221 usb_endpoint_mapping_t *pipes = 222 calloc(pipe_count, sizeof(usb_endpoint_mapping_t)); 318 223 if (pipes == NULL) { 319 224 return ENOMEM; … … 321 226 322 227 /* Now initialize. */ 323 for ( i = 0; i < pipe_count; i++) {228 for (size_t i = 0; i < pipe_count; i++) { 324 229 pipes[i].description = endpoints[i]; 325 pipes[i].interface_no = interface_no; 326 pipes[i].interface_setting = interface_setting; 230 pipes[i].interface_no = usb_dev->interface_no; 231 pipes[i].interface_setting = 232 usb_dev->alternate_interfaces.current; 327 233 } 328 234 329 235 /* Find the mapping from configuration descriptor. */ 330 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count, 331 config_descr, config_descr_size, wire); 236 int rc = usb_pipe_initialize_from_configuration(pipes, pipe_count, 237 usb_dev->descriptors.full_config, 238 usb_dev->descriptors.full_config_size, 239 usb_dev->bus_session); 332 240 if (rc != EOK) { 333 241 free(pipes); … … 336 244 337 245 /* Register created pipes. */ 338 for ( i = 0; i < pipe_count; i++) {246 for (size_t i = 0; i < pipe_count; i++) { 339 247 if (pipes[i].present) { 340 248 rc = usb_pipe_register(&pipes[i].pipe, … … 346 254 } 347 255 348 *pipes_ptr = pipes; 349 if (pipes_count_ptr != NULL) { 350 *pipes_count_ptr = pipe_count; 351 } 256 usb_dev->pipes = pipes; 257 usb_dev->pipes_count = pipe_count; 352 258 353 259 return EOK; … … 360 266 */ 361 267 rollback_unregister_endpoints: 362 for ( i = 0; i < pipe_count; i++) {268 for (size_t i = 0; i < pipe_count; i++) { 363 269 if (pipes[i].present) { 364 270 usb_pipe_unregister(&pipes[i].pipe); … … 372 278 /** Destroy pipes previously created by usb_device_create_pipes. 373 279 * 374 * @param[in] pipes Endpoint mapping to be destroyed. 375 * @param[in] pipes_count Number of endpoints. 376 */ 377 void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count) 378 { 280 * @param[in] usb_dev USB device. 281 */ 282 void usb_device_destroy_pipes(usb_device_t *usb_dev) 283 { 284 assert(usb_dev); 285 assert(usb_dev->pipes || usb_dev->pipes_count == 0); 379 286 /* Destroy the pipes. */ 380 for (size_t i = 0; i < pipes_count; ++i) { 381 assert(pipes); 287 for (size_t i = 0; i < usb_dev->pipes_count; ++i) { 382 288 usb_log_debug2("Unregistering pipe %zu: %spresent.\n", 383 i, pipes[i].present ? "" : "not "); 384 if (pipes[i].present) 385 usb_pipe_unregister(&pipes[i].pipe); 386 } 387 free(pipes); 289 i, usb_dev->pipes[i].present ? "" : "not "); 290 if (usb_dev->pipes[i].present) 291 usb_pipe_unregister(&usb_dev->pipes[i].pipe); 292 } 293 free(usb_dev->pipes); 294 usb_dev->pipes = NULL; 295 usb_dev->pipes_count = 0; 296 } 297 298 usb_pipe_t *usb_device_get_default_pipe(usb_device_t *usb_dev) 299 { 300 assert(usb_dev); 301 return &usb_dev->ctrl_pipe; 302 } 303 304 usb_endpoint_mapping_t *usb_device_get_mapped_ep_desc(usb_device_t *usb_dev, 305 const usb_endpoint_description_t *desc) 306 { 307 assert(usb_dev); 308 for (unsigned i = 0; i < usb_dev->pipes_count; ++i) { 309 if (usb_dev->pipes[i].description == desc) 310 return &usb_dev->pipes[i]; 311 } 312 return NULL; 313 } 314 315 usb_endpoint_mapping_t * usb_device_get_mapped_ep( 316 usb_device_t *usb_dev, usb_endpoint_t ep) 317 { 318 assert(usb_dev); 319 for (unsigned i = 0; i < usb_dev->pipes_count; ++i) { 320 if (usb_dev->pipes[i].pipe.endpoint_no == ep) 321 return &usb_dev->pipes[i]; 322 } 323 return NULL; 324 } 325 326 int usb_device_get_iface_number(usb_device_t *usb_dev) 327 { 328 assert(usb_dev); 329 return usb_dev->interface_no; 330 } 331 332 devman_handle_t usb_device_get_devman_handle(usb_device_t *usb_dev) 333 { 334 assert(usb_dev); 335 return usb_dev->handle; 336 } 337 338 const usb_device_descriptors_t *usb_device_descriptors(usb_device_t *usb_dev) 339 { 340 assert(usb_dev); 341 return &usb_dev->descriptors; 342 } 343 344 const usb_alternate_interfaces_t * usb_device_get_alternative_ifaces( 345 usb_device_t *usb_dev) 346 { 347 assert(usb_dev); 348 return &usb_dev->alternate_interfaces; 349 } 350 351 /** Clean instance of a USB device. 352 * 353 * @param dev Device to be de-initialized. 354 * 355 * Does not free/destroy supplied pointer. 356 */ 357 static void usb_device_fini(usb_device_t *usb_dev) 358 { 359 if (usb_dev) { 360 /* Destroy existing pipes. */ 361 usb_device_destroy_pipes(usb_dev); 362 /* Ignore errors and hope for the best. */ 363 usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces); 364 usb_device_release_descriptors(usb_dev); 365 free(usb_dev->driver_data); 366 usb_dev->driver_data = NULL; 367 usb_dev_disconnect(usb_dev->bus_session); 368 usb_dev->bus_session = NULL; 369 } 388 370 } 389 371 … … 397 379 * @return Error code. 398 380 */ 399 int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev, 400 const usb_endpoint_description_t **endpoints, const char **errstr_ptr) 381 static int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev, 382 const usb_endpoint_description_t **endpoints, const char **errstr_ptr, 383 devman_handle_t handle, int interface_no) 401 384 { 402 385 assert(usb_dev != NULL); 403 assert( ddf_dev != NULL);386 assert(errstr_ptr); 404 387 405 388 *errstr_ptr = NULL; 406 389 407 390 usb_dev->ddf_dev = ddf_dev; 391 usb_dev->handle = handle; 392 usb_dev->interface_no = interface_no; 408 393 usb_dev->driver_data = NULL; 409 usb_dev->descriptors.configuration = NULL; 394 usb_dev->descriptors.full_config = NULL; 395 usb_dev->descriptors.full_config_size = 0; 410 396 usb_dev->pipes_count = 0; 411 397 usb_dev->pipes = NULL; 412 398 413 /* Get assigned params */ 414 devman_handle_t hc_handle; 415 usb_address_t address; 416 417 int rc = usb_get_info_by_handle(ddf_dev_get_handle(ddf_dev), 418 &hc_handle, &address, &usb_dev->interface_no); 419 if (rc != EOK) { 420 *errstr_ptr = "device parameters retrieval"; 421 return rc; 422 } 423 424 /* Initialize hc connection. */ 425 usb_hc_connection_initialize(&usb_dev->hc_conn, hc_handle); 426 427 /* Initialize backing wire and control pipe. */ 428 rc = usb_device_connection_initialize( 429 &usb_dev->wire, &usb_dev->hc_conn, address); 430 if (rc != EOK) { 431 *errstr_ptr = "device connection initialization"; 432 return rc; 399 usb_dev->bus_session = usb_dev_connect(handle); 400 401 if (!usb_dev->bus_session) { 402 *errstr_ptr = "device bus session create"; 403 return ENOMEM; 433 404 } 434 405 435 406 /* This pipe was registered by the hub driver, 436 407 * during device initialization. */ 437 rc = usb_pipe_initialize_default_control(438 &usb_dev->ctrl_pipe, &usb_dev->wire);408 int rc = usb_pipe_initialize_default_control( 409 &usb_dev->ctrl_pipe, usb_dev->bus_session); 439 410 if (rc != EOK) { 411 usb_dev_disconnect(usb_dev->bus_session); 440 412 *errstr_ptr = "default control pipe initialization"; 441 413 return rc; 442 414 } 443 415 444 /* Open hc connection for pipe registration. */445 rc = usb_hc_connection_open(&usb_dev->hc_conn);446 if (rc != EOK) {447 *errstr_ptr = "hc connection open";448 return rc;449 }450 451 416 /* Retrieve standard descriptors. */ 452 rc = usb_device_retrieve_descriptors( 453 &usb_dev->ctrl_pipe, &usb_dev->descriptors); 417 rc = usb_device_retrieve_descriptors(usb_dev); 454 418 if (rc != EOK) { 455 419 *errstr_ptr = "descriptor retrieval"; 456 usb_ hc_connection_close(&usb_dev->hc_conn);420 usb_dev_disconnect(usb_dev->bus_session); 457 421 return rc; 458 422 } … … 463 427 * controlling a device. */ 464 428 rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces, 465 usb_dev->descriptors.configuration, 466 usb_dev->descriptors.configuration_size, usb_dev->interface_no); 467 const int alternate_iface = 468 (rc == EOK) ? usb_dev->alternate_interfaces.current : 0; 469 470 /* Create and register other pipes than default control (EP 0) */ 471 rc = usb_device_create_pipes(&usb_dev->wire, endpoints, 472 usb_dev->descriptors.configuration, 473 usb_dev->descriptors.configuration_size, 474 usb_dev->interface_no, (int)alternate_iface, 475 &usb_dev->pipes, &usb_dev->pipes_count); 476 if (rc != EOK) { 477 usb_hc_connection_close(&usb_dev->hc_conn); 478 /* Full configuration descriptor is allocated. */ 479 usb_device_release_descriptors(&usb_dev->descriptors); 480 /* Alternate interfaces may be allocated */ 481 usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces); 482 *errstr_ptr = "pipes initialization"; 483 return rc; 484 } 485 486 usb_hc_connection_close(&usb_dev->hc_conn); 429 usb_dev->descriptors.full_config, 430 usb_dev->descriptors.full_config_size, usb_dev->interface_no); 431 432 if (endpoints) { 433 /* Create and register other pipes than default control (EP 0)*/ 434 rc = usb_device_create_pipes(usb_dev, endpoints); 435 if (rc != EOK) { 436 usb_device_fini(usb_dev); 437 *errstr_ptr = "pipes initialization"; 438 return rc; 439 } 440 } 441 487 442 return EOK; 488 443 } 489 444 490 /** Clean instance of a USB device. 491 * 492 * @param dev Device to be de-initialized. 493 * 494 * Does not free/destroy supplied pointer. 495 */ 496 void usb_device_deinit(usb_device_t *dev) 497 { 498 if (dev) { 499 /* Destroy existing pipes. */ 500 destroy_current_pipes(dev); 501 /* Ignore errors and hope for the best. */ 502 usb_hc_connection_deinitialize(&dev->hc_conn); 503 usb_alternate_interfaces_deinit(&dev->alternate_interfaces); 504 usb_device_release_descriptors(&dev->descriptors); 505 free(dev->driver_data); 506 dev->driver_data = NULL; 507 } 445 static int usb_device_get_info(async_sess_t *sess, devman_handle_t *handle, 446 int *iface_no) 447 { 448 assert(handle); 449 assert(iface_no); 450 async_exch_t *exch = async_exchange_begin(sess); 451 if (!exch) 452 return EPARTY; 453 int ret = usb_get_my_device_handle(exch, handle); 454 if (ret == EOK) { 455 ret = usb_get_my_interface(exch, iface_no); 456 if (ret == ENOTSUP) { 457 *iface_no = -1; 458 ret = EOK; 459 } 460 } 461 async_exchange_end(exch); 462 return ret; 463 } 464 465 int usb_device_create_ddf(ddf_dev_t *ddf_dev, 466 const usb_endpoint_description_t **desc, const char **err) 467 { 468 assert(ddf_dev); 469 assert(err); 470 471 devman_handle_t h = 0; 472 int iface_no = -1; 473 474 async_sess_t *sess = devman_parent_device_connect( 475 ddf_dev_get_handle(ddf_dev), IPC_FLAG_BLOCKING); 476 const int ret = usb_device_get_info(sess, &h, &iface_no); 477 async_hangup(sess); 478 if (ret != EOK) 479 return ret; 480 481 usb_device_t *usb_dev = 482 ddf_dev_data_alloc(ddf_dev, sizeof(usb_device_t)); 483 if (usb_dev == NULL) { 484 *err = "DDF data alloc"; 485 return ENOMEM; 486 } 487 488 return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no); 489 } 490 491 void usb_device_destroy_ddf(ddf_dev_t *ddf_dev) 492 { 493 assert(ddf_dev); 494 usb_device_t *usb_dev = ddf_dev_data_get(ddf_dev); 495 assert(usb_dev); 496 usb_device_fini(usb_dev); 497 return; 498 } 499 500 usb_device_t * usb_device_create(devman_handle_t handle) 501 { 502 devman_handle_t h = 0; 503 int iface_no = -1; 504 505 async_sess_t *sess = devman_device_connect(handle, IPC_FLAG_BLOCKING); 506 int ret = usb_device_get_info(sess, &h, &iface_no); 507 if (sess) 508 async_hangup(sess); 509 if (ret != EOK) 510 return NULL; 511 512 usb_device_t *usb_dev = malloc(sizeof(usb_device_t)); 513 if (!usb_dev) 514 return NULL; 515 516 const char* dummy = NULL; 517 ret = usb_device_init(usb_dev, NULL, NULL, &dummy, handle, iface_no); 518 if (ret != EOK) { 519 free(usb_dev); 520 usb_dev = NULL; 521 } 522 return usb_dev; 523 } 524 525 void usb_device_destroy(usb_device_t *usb_dev) 526 { 527 if (usb_dev) { 528 usb_device_fini(usb_dev); 529 free(usb_dev); 530 } 531 } 532 533 const char *usb_device_get_name(usb_device_t *usb_dev) 534 { 535 assert(usb_dev); 536 if (usb_dev->ddf_dev) 537 return ddf_dev_get_name(usb_dev->ddf_dev); 538 return NULL; 539 } 540 541 ddf_fun_t *usb_device_ddf_fun_create(usb_device_t *usb_dev, fun_type_t ftype, 542 const char* name) 543 { 544 assert(usb_dev); 545 if (usb_dev->ddf_dev) 546 return ddf_fun_create(usb_dev->ddf_dev, ftype, name); 547 return NULL; 548 } 549 550 async_exch_t * usb_device_bus_exchange_begin(usb_device_t *usb_dev) 551 { 552 assert(usb_dev); 553 return async_exchange_begin(usb_dev->bus_session); 554 } 555 556 void usb_device_bus_exchange_end(async_exch_t *exch) 557 { 558 async_exchange_end(exch); 508 559 } 509 560 … … 521 572 } 522 573 574 void * usb_device_data_get(usb_device_t *usb_dev) 575 { 576 assert(usb_dev); 577 return usb_dev->driver_data; 578 } 579 523 580 /** 524 581 * @} -
uspace/lib/usbdev/src/devpoll.c
r5b18137 rb4b534ac 33 33 * USB device driver framework - automatic interrupt polling. 34 34 */ 35 #include <usb/dev/device.h> 36 #include <usb/dev/pipes.h> 35 37 #include <usb/dev/poll.h> 36 38 #include <usb/dev/request.h> 39 #include <usb/classes/classes.h> 37 40 #include <usb/debug.h> 38 #include <usb/classes/classes.h> 41 #include <usb/descriptor.h> 42 #include <usb/usb.h> 43 44 #include <assert.h> 45 #include <async.h> 39 46 #include <errno.h> 47 #include <fibril.h> 48 #include <stdbool.h> 49 #include <stdlib.h> 40 50 #include <str_error.h> 41 #include < assert.h>51 #include <sys/types.h> 42 52 43 53 /** Maximum number of failed consecutive requests before announcing failure. */ … … 51 61 /** USB device to poll. */ 52 62 usb_device_t *dev; 53 /** Device pipeto use for polling. */54 size_t pipe_index;63 /** Device enpoint mapping to use for polling. */ 64 usb_endpoint_mapping_t *polling_mapping; 55 65 /** Size of the recieved data. */ 56 66 size_t request_size; … … 72 82 const usb_device_auto_polling_t *params = &data->auto_polling; 73 83 74 usb_pipe_t *pipe 75 = &data->dev->pipes[data->pipe_index].pipe; 84 usb_pipe_t *pipe = &data->polling_mapping->pipe; 76 85 77 86 if (params->debug > 0) { 78 87 const usb_endpoint_mapping_t *mapping 79 = &data->dev->pipes[data->pipe_index];80 usb_log_debug("Poll %p: started polling of `%s' - " \88 = data->polling_mapping; 89 usb_log_debug("Poll (%p): started polling of `%s' - " \ 81 90 "interface %d (%s,%d,%d), %zuB/%zu.\n", 82 data, ddf_dev_get_name(data->dev->ddf_dev),91 data, usb_device_get_name(data->dev), 83 92 (int) mapping->interface->interface_number, 84 93 usb_str_class(mapping->interface->interface_class), … … 88 97 } 89 98 90 usb_pipe_start_long_transfer(pipe);91 99 size_t failed_attempts = 0; 92 100 while (failed_attempts <= params->max_failures) { … … 95 103 data->request_size, &actual_size); 96 104 97 if ( params->debug > 1) {98 if ( rc == EOK) {105 if (rc == EOK) { 106 if (params->debug > 1) { 99 107 usb_log_debug( 100 108 "Poll%p: received: '%s' (%zuB).\n", … … 103 111 actual_size, 16), 104 112 actual_size); 105 } else { 113 } 114 } else { 106 115 usb_log_debug( 107 116 "Poll%p: polling failed: %s.\n", 108 117 data, str_error(rc)); 109 }110 118 } 111 119 … … 117 125 */ 118 126 usb_request_clear_endpoint_halt( 119 &data->dev->ctrl_pipe, pipe->endpoint_no); 127 usb_device_get_default_pipe(data->dev), 128 pipe->endpoint_no); 120 129 } 121 130 … … 145 154 146 155 /* Take a rest before next request. */ 156 //TODO: This is broken, the time is in ms not us. 157 // but first we need to fix drivers to actually stop using this, 158 // since polling dealy should be implemented in HC schedule 147 159 async_usleep(params->delay); 148 160 } 149 150 usb_pipe_end_long_transfer(pipe);151 161 152 162 const bool failed = failed_attempts > 0; … … 159 169 if (failed) { 160 170 usb_log_error("Polling of device `%s' terminated: " 161 "recurring failures.\n", ddf_dev_get_name(162 data->dev->ddf_dev));171 "recurring failures.\n", 172 usb_device_get_name(data->dev)); 163 173 } else { 164 174 usb_log_debug("Polling of device `%s' terminated: " 165 "driver request.\n", ddf_dev_get_name(166 data->dev->ddf_dev));175 "driver request.\n", 176 usb_device_get_name(data->dev)); 167 177 } 168 178 } … … 175 185 } 176 186 187 177 188 /** Start automatic device polling over interrupt in pipe. 178 189 * 179 * @warning It is up to the callback to produce delays between individual180 * requests.190 * The polling settings is copied thus it is okay to destroy the structure 191 * after this function returns. 181 192 * 182 193 * @warning There is no guarantee when the request to the device … … 185 196 * 186 197 * @param dev Device to be periodically polled. 198 * @param epm Endpoint mapping to use. 199 * @param polling Polling settings. 200 * @param request_size How many bytes to ask for in each request. 201 * @param arg Custom argument (passed as is to the callbacks). 202 * @return Error code. 203 * @retval EOK New fibril polling the device was already started. 204 */ 205 static int usb_device_auto_polling_internal(usb_device_t *dev, 206 usb_endpoint_mapping_t *epm, const usb_device_auto_polling_t *polling, 207 size_t request_size) 208 { 209 if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) { 210 return EBADMEM; 211 } 212 213 if (request_size == 0) 214 return EINVAL; 215 216 if (!epm || (epm->pipe.transfer_type != USB_TRANSFER_INTERRUPT) || 217 (epm->pipe.direction != USB_DIRECTION_IN)) 218 return EINVAL; 219 220 221 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); 222 if (polling_data == NULL) { 223 return ENOMEM; 224 } 225 226 /* Fill-in the data. */ 227 polling_data->buffer = malloc(sizeof(request_size)); 228 if (polling_data->buffer == NULL) { 229 free(polling_data); 230 return ENOMEM; 231 } 232 polling_data->request_size = request_size; 233 polling_data->dev = dev; 234 polling_data->polling_mapping = epm; 235 236 /* Copy provided settings. */ 237 polling_data->auto_polling = *polling; 238 239 /* Negative value means use descriptor provided value. */ 240 if (polling->delay < 0) { 241 polling_data->auto_polling.delay = 242 epm->descriptor->poll_interval; 243 } 244 245 fid_t fibril = fibril_create(polling_fibril, polling_data); 246 if (fibril == 0) { 247 free(polling_data->buffer); 248 free(polling_data); 249 return ENOMEM; 250 } 251 fibril_add_ready(fibril); 252 253 /* Fibril launched. That fibril will free the allocated data. */ 254 255 return EOK; 256 } 257 /** Start automatic device polling over interrupt in pipe. 258 * 259 * The polling settings is copied thus it is okay to destroy the structure 260 * after this function returns. 261 * 262 * @warning There is no guarantee when the request to the device 263 * will be sent for the first time (it is possible that this 264 * first request would be executed prior to return from this function). 265 * 266 * @param dev Device to be periodically polled. 187 267 * @param pipe_index Index of the endpoint pipe used for polling. 268 * @param polling Polling settings. 269 * @param req_size How many bytes to ask for in each request. 270 * @param arg Custom argument (passed as is to the callbacks). 271 * @return Error code. 272 * @retval EOK New fibril polling the device was already started. 273 */ 274 int usb_device_auto_polling(usb_device_t *usb_dev, usb_endpoint_t ep, 275 const usb_device_auto_polling_t *polling, size_t req_size) 276 { 277 usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(usb_dev, ep); 278 return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size); 279 } 280 281 /** Start automatic device polling over interrupt in pipe. 282 * 283 * @warning It is up to the callback to produce delays between individual 284 * requests. 285 * 286 * @warning There is no guarantee when the request to the device 287 * will be sent for the first time (it is possible that this 288 * first request would be executed prior to return from this function). 289 * 290 * @param dev Device to be periodically polled. 291 * @param ep Endpoint used for polling. 188 292 * @param callback Callback when data are available. 189 293 * @param request_size How many bytes to ask for in each request. 294 * @param delay NUmber of ms to wait between queries, -1 to use descriptor val. 190 295 * @param terminated_callback Callback when polling is terminated. 191 296 * @param arg Custom argument (passed as is to the callbacks). … … 193 298 * @retval EOK New fibril polling the device was already started. 194 299 */ 195 int usb_device_auto_poll(usb_device_t *dev, size_t pipe_index,196 usb_polling_callback_t callback, size_t request_size, 300 int usb_device_auto_poll(usb_device_t *dev, usb_endpoint_t ep, 301 usb_polling_callback_t callback, size_t request_size, int delay, 197 302 usb_polling_terminted_callback_t terminated_callback, void *arg) 198 303 { … … 200 305 .debug = 1, 201 306 .auto_clear_halt = true, 202 .delay = 0,307 .delay = delay, 203 308 .max_failures = MAX_FAILED_ATTEMPTS, 204 309 .on_data = callback, … … 208 313 }; 209 314 210 return usb_device_auto_polling(dev, pipe_index, &auto_polling, 211 request_size); 212 } 213 214 /** Start automatic device polling over interrupt in pipe. 215 * 216 * The polling settings is copied thus it is okay to destroy the structure 217 * after this function returns. 218 * 219 * @warning There is no guarantee when the request to the device 220 * will be sent for the first time (it is possible that this 221 * first request would be executed prior to return from this function). 222 * 223 * @param dev Device to be periodically polled. 224 * @param pipe_index Index of the endpoint pipe used for polling. 225 * @param polling Polling settings. 226 * @param request_size How many bytes to ask for in each request. 227 * @param arg Custom argument (passed as is to the callbacks). 228 * @return Error code. 229 * @retval EOK New fibril polling the device was already started. 230 */ 231 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index, 232 const usb_device_auto_polling_t *polling, 233 size_t request_size) 234 { 235 if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) { 236 return EBADMEM; 237 } 238 239 if (pipe_index >= dev->pipes_count || request_size == 0) { 240 return EINVAL; 241 } 242 if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT) 243 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) { 244 return EINVAL; 245 } 246 247 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); 248 if (polling_data == NULL) { 249 return ENOMEM; 250 } 251 252 /* Fill-in the data. */ 253 polling_data->buffer = malloc(sizeof(request_size)); 254 if (polling_data->buffer == NULL) { 255 free(polling_data); 256 return ENOMEM; 257 } 258 polling_data->request_size = request_size; 259 polling_data->dev = dev; 260 polling_data->pipe_index = pipe_index; 261 262 /* Copy provided settings. */ 263 polling_data->auto_polling = *polling; 264 265 /* Negative value means use descriptor provided value. */ 266 if (polling->delay < 0) { 267 polling_data->auto_polling.delay = 268 (int) dev->pipes[pipe_index].descriptor->poll_interval; 269 } 270 271 fid_t fibril = fibril_create(polling_fibril, polling_data); 272 if (fibril == 0) { 273 free(polling_data->buffer); 274 free(polling_data); 275 return ENOMEM; 276 } 277 fibril_add_ready(fibril); 278 279 /* Fibril launched. That fibril will free the allocated data. */ 280 281 return EOK; 315 usb_endpoint_mapping_t *epm = usb_device_get_mapped_ep(dev, ep); 316 return usb_device_auto_polling_internal( 317 dev, epm, &auto_polling, request_size); 318 } 319 320 int usb_device_auto_polling_desc(usb_device_t *usb_dev, 321 const usb_endpoint_description_t *desc, 322 const usb_device_auto_polling_t *polling, size_t req_size) 323 { 324 usb_endpoint_mapping_t *epm = 325 usb_device_get_mapped_ep_desc(usb_dev, desc); 326 return usb_device_auto_polling_internal(usb_dev, epm, polling, req_size); 327 } 328 329 int usb_device_auto_poll_desc(usb_device_t * usb_dev, 330 const usb_endpoint_description_t *desc, usb_polling_callback_t callback, 331 size_t req_size, int delay, 332 usb_polling_terminted_callback_t terminated_callback, void *arg) 333 { 334 const usb_device_auto_polling_t auto_polling = { 335 .debug = 1, 336 .auto_clear_halt = true, 337 .delay = delay, 338 .max_failures = MAX_FAILED_ATTEMPTS, 339 .on_data = callback, 340 .on_polling_end = terminated_callback, 341 .on_error = NULL, 342 .arg = arg, 343 }; 344 345 usb_endpoint_mapping_t *epm = 346 usb_device_get_mapped_ep_desc(usb_dev, desc); 347 return usb_device_auto_polling_internal( 348 usb_dev, epm, &auto_polling, req_size); 282 349 } 283 350 -
uspace/lib/usbdev/src/dp.c
r5b18137 rb4b534ac 41 41 * sibling. 42 42 */ 43 #include <stdio.h>44 #include <str_error.h>45 #include <errno.h>46 #include <assert.h>47 #include <stdbool.h>48 43 #include <usb/dev/dp.h> 49 44 #include <usb/descriptor.h> 45 46 #include <assert.h> 47 #include <errno.h> 48 #include <stdlib.h> 49 #include <stdbool.h> 50 #include <sys/types.h> 50 51 51 52 #define NESTING(parentname, childname) \ … … 304 305 * @param arg Custom (user) argument. 305 306 */ 306 void usb_dp_walk_simple( uint8_t *descriptors, size_t descriptors_size,307 void usb_dp_walk_simple(const uint8_t *descriptors, size_t descriptors_size, 307 308 const usb_dp_descriptor_nesting_t *descriptor_nesting, 308 309 walk_callback_t callback, void *arg) -
uspace/lib/usbdev/src/pipes.c
r5b18137 rb4b534ac 35 35 #include <usb/dev/pipes.h> 36 36 #include <usb/dev/request.h> 37 #include <usb/usb.h> 38 #include <usb_iface.h> 39 40 #include <assert.h> 41 #include <async.h> 37 42 #include <errno.h> 38 #include <assert.h> 39 40 /** Prepare pipe for a long transfer. 41 * 42 * Long transfer is transfer consisting of several requests to the HC. 43 * Calling this function is optional and it has positive effect of 44 * improved performance because IPC session is initiated only once. 45 * 46 * @param pipe Pipe over which the transfer will happen. 47 * @return Error code. 48 */ 49 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 50 { 51 assert(pipe); 52 assert(pipe->wire); 53 assert(pipe->wire->hc_connection); 54 return usb_hc_connection_open(pipe->wire->hc_connection); 55 } 56 57 /** Terminate a long transfer on a pipe. 58 * @param pipe Pipe where to end the long transfer. 59 * @return Error code. 60 * @see usb_pipe_start_long_transfer 61 */ 62 int usb_pipe_end_long_transfer(usb_pipe_t *pipe) 63 { 64 assert(pipe); 65 assert(pipe->wire); 66 assert(pipe->wire->hc_connection); 67 return usb_hc_connection_close(pipe->wire->hc_connection); 68 } 43 #include <mem.h> 69 44 70 45 /** Try to clear endpoint halt of default control pipe. … … 121 96 memcpy(&setup_packet, setup_buffer, 8); 122 97 98 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 123 99 size_t act_size = 0; 124 const int rc = usb_ device_control_read(pipe->wire,100 const int rc = usb_read(exch, 125 101 pipe->endpoint_no, setup_packet, buffer, buffer_size, &act_size); 102 async_exchange_end(exch); 126 103 127 104 if (rc == ESTALL) { … … 173 150 memcpy(&setup_packet, setup_buffer, 8); 174 151 175 const int rc = usb_device_control_write(pipe->wire, 152 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 153 const int rc = usb_write(exch, 176 154 pipe->endpoint_no, setup_packet, buffer, buffer_size); 155 async_exchange_end(exch); 177 156 178 157 if (rc == ESTALL) { … … 217 196 return ENOTSUP; 218 197 198 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 219 199 size_t act_size = 0; 220 const int rc = usb_device_read(pipe->wire, 221 pipe->endpoint_no, buffer, size, &act_size); 200 const int rc = 201 usb_read(exch, pipe->endpoint_no, 0, buffer, size, &act_size); 202 async_exchange_end(exch); 222 203 223 204 if (rc == EOK && size_transfered != NULL) { … … 256 237 return ENOTSUP; 257 238 258 return usb_device_write(pipe->wire, 259 pipe->endpoint_no, buffer, size); 239 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 240 const int rc = usb_write(exch, pipe->endpoint_no, 0, buffer, size); 241 async_exchange_end(exch); 242 return rc; 260 243 } 261 244 … … 263 246 * 264 247 * @param pipe Endpoint pipe to be initialized. 265 * @param connection Connection to the USB device backing this pipe (the wire).266 248 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15). 267 249 * @param transfer_type Transfer type (e.g. interrupt or bulk). … … 270 252 * @return Error code. 271 253 */ 272 int usb_pipe_initialize(usb_pipe_t *pipe, 273 usb_device_connection_t *connection, usb_endpoint_t endpoint_no, 254 int usb_pipe_initialize(usb_pipe_t *pipe, usb_endpoint_t endpoint_no, 274 255 usb_transfer_type_t transfer_type, size_t max_packet_size, 275 usb_direction_t direction) 276 { 277 assert(pipe); 278 assert(connection); 279 280 pipe->wire = connection; 256 usb_direction_t direction, unsigned packets, usb_dev_session_t *bus_session) 257 { 258 assert(pipe); 259 281 260 pipe->endpoint_no = endpoint_no; 282 261 pipe->transfer_type = transfer_type; 262 pipe->packets = packets; 283 263 pipe->max_packet_size = max_packet_size; 284 264 pipe->direction = direction; 285 265 pipe->auto_reset_halt = false; 266 pipe->bus_session = bus_session; 286 267 287 268 return EOK; … … 291 272 * 292 273 * @param pipe Endpoint pipe to be initialized. 293 * @param connection Connection to the USB device backing this pipe (the wire).294 274 * @return Error code. 295 275 */ 296 276 int usb_pipe_initialize_default_control(usb_pipe_t *pipe, 297 usb_device_connection_t *connection) 298 { 299 assert(pipe); 300 assert(connection); 301 302 int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL, 303 CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH); 277 usb_dev_session_t *bus_session) 278 { 279 assert(pipe); 280 281 const int rc = usb_pipe_initialize(pipe, 0, USB_TRANSFER_CONTROL, 282 CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH, 1, bus_session); 304 283 305 284 pipe->auto_reset_halt = true; … … 317 296 { 318 297 assert(pipe); 319 assert(pipe->wire); 320 321 return usb_device_register_endpoint(pipe->wire, 322 pipe->endpoint_no, pipe->transfer_type, 323 pipe->direction, pipe->max_packet_size, interval); 298 assert(pipe->bus_session); 299 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 300 if (!exch) 301 return ENOMEM; 302 const int ret = usb_register_endpoint(exch, pipe->endpoint_no, 303 pipe->transfer_type, pipe->direction, pipe->max_packet_size, 304 pipe->packets, interval); 305 async_exchange_end(exch); 306 return ret; 324 307 } 325 308 … … 332 315 { 333 316 assert(pipe); 334 assert(pipe->wire); 335 336 return usb_device_unregister_endpoint(pipe->wire, 337 pipe->endpoint_no, pipe->direction); 317 assert(pipe->bus_session); 318 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 319 if (!exch) 320 return ENOMEM; 321 const int ret = usb_unregister_endpoint(exch, pipe->endpoint_no, 322 pipe->direction); 323 async_exchange_end(exch); 324 return ret; 338 325 } 339 326 -
uspace/lib/usbdev/src/pipesinit.c
r5b18137 rb4b534ac 34 34 * 35 35 */ 36 #include <usb/usb.h>37 36 #include <usb/dev/pipes.h> 38 37 #include <usb/dev/dp.h> 39 38 #include <usb/dev/request.h> 39 #include <usb/usb.h> 40 #include <usb/descriptor.h> 41 42 #include <assert.h> 40 43 #include <errno.h> 41 #include <assert.h>42 44 43 45 #define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7 … … 148 150 * @param interface Interface descriptor under which belongs the @p endpoint. 149 151 * @param endpoint Endpoint descriptor. 150 * @param wire Connection backing the endpoint pipes.151 152 * @return Error code. 152 153 */ … … 155 156 usb_standard_interface_descriptor_t *interface, 156 157 usb_standard_endpoint_descriptor_t *endpoint_desc, 157 usb_dev ice_connection_t *wire)158 usb_dev_session_t *bus_session) 158 159 { 159 160 … … 193 194 } 194 195 195 int rc = usb_pipe_initialize(&ep_mapping->pipe, wire,196 int rc = usb_pipe_initialize(&ep_mapping->pipe, 196 197 ep_no, description.transfer_type, 197 uint16_usb2host(endpoint_desc->max_packet_size), 198 description.direction); 198 ED_MPS_PACKET_SIZE_GET( 199 uint16_usb2host(endpoint_desc->max_packet_size)), 200 description.direction, 201 ED_MPS_TRANS_OPPORTUNITIES_GET( 202 uint16_usb2host(endpoint_desc->max_packet_size)), bus_session); 199 203 if (rc != EOK) { 200 204 return rc; … … 220 224 usb_endpoint_mapping_t *mapping, size_t mapping_count, 221 225 const usb_dp_parser_t *parser, const usb_dp_parser_data_t *parser_data, 222 const uint8_t *interface_descriptor )226 const uint8_t *interface_descriptor, usb_dev_session_t *bus_session) 223 227 { 224 228 const uint8_t *descriptor = usb_dp_get_nested_descriptor(parser, … … 236 240 (usb_standard_endpoint_descriptor_t *) 237 241 descriptor, 238 (usb_device_connection_t *) parser_data->arg);242 bus_session); 239 243 } 240 244 … … 280 284 usb_endpoint_mapping_t *mapping, size_t mapping_count, 281 285 const uint8_t *config_descriptor, size_t config_descriptor_size, 282 usb_device_connection_t *connection) 283 { 284 assert(connection); 286 usb_dev_session_t *bus_session) 287 { 285 288 286 289 if (config_descriptor == NULL) { … … 306 309 .data = config_descriptor, 307 310 .size = config_descriptor_size, 308 .arg = connection309 311 }; 310 312 … … 319 321 do { 320 322 (void) process_interface(mapping, mapping_count, 321 &dp_parser, &dp_data, interface );323 &dp_parser, &dp_data, interface, bus_session); 322 324 interface = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 323 325 config_descriptor, interface); … … 347 349 return EINVAL; 348 350 } 349 350 351 usb_pipe_start_long_transfer(pipe);352 351 353 352 uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE]; … … 367 366 } 368 367 } 369 usb_pipe_end_long_transfer(pipe);370 368 if (rc != EOK) { 371 369 return rc; -
uspace/lib/usbdev/src/recognise.c
r5b18137 rb4b534ac 34 34 */ 35 35 36 #include <sys/types.h>37 #include <fibril_synch.h>38 #include <usb/debug.h>39 #include <usb/dev/hub.h>40 36 #include <usb/dev/pipes.h> 41 37 #include <usb/dev/recognise.h> 42 #include <usb/ddfiface.h>43 38 #include <usb/dev/request.h> 44 39 #include <usb/classes/classes.h> 40 41 #include <assert.h> 42 #include <errno.h> 45 43 #include <stdio.h> 46 #include <errno.h> 47 #include <assert.h> 48 49 /** DDF operations of child devices. */ 50 static ddf_dev_ops_t child_ops = { 51 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl 52 }; 44 #include <sys/types.h> 53 45 54 46 /** Get integer part from BCD coded number. */ … … 242 234 (int) device_descriptor->product_id, 243 235 BCD_ARGS(device_descriptor->device_version)); 244 236 245 237 /* Next, without release number. */ 246 238 ADD_MATCHID_OR_RETURN(matches, 90, … … 248 240 (int) device_descriptor->vendor_id, 249 241 (int) device_descriptor->product_id); 250 } 251 252 /* 253 * If the device class points to interface we skip adding 254 * class directly but we add a multi interface device. 255 */ 256 if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) { 257 ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s", 258 usb_str_class(device_descriptor->device_class)); 259 } else { 260 ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid"); 261 } 262 242 } 243 244 /* Class match id */ 245 ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s", 246 usb_str_class(device_descriptor->device_class)); 247 263 248 /* As a last resort, try fallback driver. */ 264 249 ADD_MATCHID_OR_RETURN(matches, 10, "usb&fallback"); … … 302 287 } 303 288 304 /** Probe for device kind and register it in devman.305 *306 * @param[in] ctrl_pipe Control pipe to the device.307 * @param[in] parent Parent device.308 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.309 * @param[in] dev_data Arbitrary pointer to be stored in the child310 * as @c driver_data.311 * @param[out] child_fun Storage where pointer to allocated child function312 * will be written.313 * @return Error code.314 *315 */316 int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,317 ddf_dev_t *parent, ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)318 {319 if (ctrl_pipe == NULL)320 return EINVAL;321 322 if (!dev_ops && ddf_fun_data_get(fun) != NULL) {323 usb_log_warning("Using standard fun ops with arbitrary "324 "driver data. This does not have to work.\n");325 }326 327 /** Index to append after device name for uniqueness. */328 static atomic_t device_name_index = {0};329 const size_t this_device_name_index =330 (size_t) atomic_preinc(&device_name_index);331 332 int rc;333 334 /*335 * TODO: Once the device driver framework support persistent336 * naming etc., something more descriptive could be created.337 */338 char child_name[12]; /* The format is: "usbAB_aXYZ", length 11 */339 rc = snprintf(child_name, sizeof(child_name),340 "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address);341 if (rc < 0) {342 goto failure;343 }344 345 rc = ddf_fun_set_name(fun, child_name);346 if (rc != EOK)347 goto failure;348 349 if (dev_ops != NULL)350 ddf_fun_set_ops(fun, dev_ops);351 else352 ddf_fun_set_ops(fun, &child_ops);353 354 /*355 * Store the attached device in fun356 * driver data if there is no other data357 */358 if (ddf_fun_data_get(fun) == NULL) {359 usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(360 fun, sizeof(usb_hub_attached_device_t));361 if (!new_device) {362 rc = ENOMEM;363 goto failure;364 }365 366 new_device->address = ctrl_pipe->wire->address;367 new_device->fun = fun;368 }369 370 match_id_list_t match_ids;371 init_match_ids(&match_ids);372 rc = usb_device_create_match_ids(ctrl_pipe, &match_ids);373 if (rc != EOK)374 goto failure;375 376 list_foreach(match_ids.ids, link, match_id_t, match_id) {377 rc = ddf_fun_add_match_id(fun, match_id->id, match_id->score);378 if (rc != EOK) {379 clean_match_ids(&match_ids);380 goto failure;381 }382 }383 384 clean_match_ids(&match_ids);385 386 rc = ddf_fun_bind(fun);387 if (rc != EOK)388 goto failure;389 390 return EOK;391 392 failure:393 return rc;394 }395 396 289 /** 397 290 * @} -
uspace/lib/usbdev/src/request.c
r5b18137 rb4b534ac 34 34 */ 35 35 #include <usb/dev/request.h> 36 #include <usb/request.h> 37 #include <usb/usb.h> 38 36 39 #include <errno.h> 37 #include <assert.h> 38 #include <usb/debug.h> 40 #include <mem.h> 41 #include <stdlib.h> 42 #include <str.h> 39 43 40 44 #define MAX_DATA_LENGTH ((size_t)(0xFFFF)) … … 51 55 * @param request Actual request (e.g. GET_DESCRIPTOR). 52 56 * @param value Value of @c wValue field of setup packet 53 * 57 * (must be in USB endianness). 54 58 * @param index Value of @c wIndex field of setup packet 55 * 59 * (must be in USB endianness). 56 60 * @param data Data to be sent during DATA stage 57 * 61 * (expected to be in USB endianness). 58 62 * @param data_size Size of the @p data buffer (in native endianness). 59 63 * @return Error code. … … 64 68 int usb_control_request_set(usb_pipe_t *pipe, 65 69 usb_request_type_t request_type, usb_request_recipient_t recipient, 66 uint8_t request, 67 uint16_t value, uint16_t index, 68 void *data, size_t data_size) 70 uint8_t request, uint16_t value, uint16_t index, 71 const void *data, size_t data_size) 69 72 { 70 73 if (pipe == NULL) { … … 85 88 */ 86 89 87 usb_device_request_setup_packet_t setup_packet; 88 setup_packet.request_type = (request_type << 5) | recipient; 89 setup_packet.request = request; 90 setup_packet.value = value; 91 setup_packet.index = index; 92 setup_packet.length = (uint16_t) data_size; 93 94 int rc = usb_pipe_control_write(pipe, 95 &setup_packet, sizeof(setup_packet), 96 data, data_size); 97 98 return rc; 90 const usb_device_request_setup_packet_t setup_packet = { 91 .request_type = (request_type << 5) | recipient, 92 .request = request, 93 .value = value, 94 .index = index, 95 .length = (uint16_t) data_size, 96 }; 97 98 return usb_pipe_control_write(pipe, 99 &setup_packet, sizeof(setup_packet), data, data_size); 99 100 } 100 101 … … 108 109 * @param request Actual request (e.g. GET_DESCRIPTOR). 109 110 * @param value Value of @c wValue field of setup packet 110 * 111 * (must be in USB endianness). 111 112 * @param index Value of @c wIndex field of setup packet 112 113 * (must be in USB endianness). … … 114 115 * (they will come in USB endianness). 115 116 * @param data_size Size of the @p data buffer 116 * 117 * (in native endianness). 117 118 * @param actual_data_size Actual size of transfered data 118 * 119 * (in native endianness). 119 120 * @return Error code. 120 121 * @retval EBADMEM @p pipe is NULL. … … 124 125 int usb_control_request_get(usb_pipe_t *pipe, 125 126 usb_request_type_t request_type, usb_request_recipient_t recipient, 126 uint8_t request, 127 uint16_t value, uint16_t index, 127 uint8_t request, uint16_t value, uint16_t index, 128 128 void *data, size_t data_size, size_t *actual_data_size) 129 129 { … … 209 209 { 210 210 if (request_type == USB_REQUEST_TYPE_STANDARD) { 211 if ((recipient == USB_REQUEST_RECIPIENT_DEVICE) 212 && (index != 0)){211 if ((recipient == USB_REQUEST_RECIPIENT_DEVICE) && (index != 0)) 212 { 213 213 return EINVAL; 214 214 } 215 215 } 216 216 217 int rc = usb_control_request_set(pipe, request_type, recipient, 218 USB_DEVREQ_CLEAR_FEATURE, 219 uint16_host2usb(feature_selector), uint16_host2usb(index), 220 NULL, 0); 221 222 return rc; 217 return usb_control_request_set(pipe, 218 request_type, recipient, USB_DEVREQ_CLEAR_FEATURE, 219 uint16_host2usb(feature_selector), uint16_host2usb(index), NULL, 0); 223 220 } 224 221 … … 237 234 { 238 235 if (request_type == USB_REQUEST_TYPE_STANDARD) { 239 if ((recipient == USB_REQUEST_RECIPIENT_DEVICE) 240 && (index != 0)){236 if ((recipient == USB_REQUEST_RECIPIENT_DEVICE) && (index != 0)) 237 { 241 238 return EINVAL; 242 239 } 243 240 } 244 241 245 int rc = usb_control_request_set(pipe, request_type, recipient, 246 USB_DEVREQ_SET_FEATURE, 247 uint16_host2usb(feature_selector), uint16_host2usb(index), 248 NULL, 0); 249 250 return rc; 242 return usb_control_request_set(pipe, 243 request_type, recipient, USB_DEVREQ_SET_FEATURE, 244 uint16_host2usb(feature_selector), uint16_host2usb(index), NULL, 0); 251 245 } 252 246 … … 277 271 } 278 272 273 /* The wValue field specifies the descriptor type in the high byte 274 * and the descriptor index in the low byte. USB 1.1 spec p. 189 275 */ 279 276 const uint16_t wValue = descriptor_index | (descriptor_type << 8); 280 277 … … 313 310 * Get only first byte to retrieve descriptor length. 314 311 */ 315 uint8_t tmp_buffer [1];312 uint8_t tmp_buffer; 316 313 size_t bytes_transfered; 317 314 rc = usb_request_get_descriptor(pipe, request_type, recipient, 318 315 descriptor_type, descriptor_index, language, 319 &tmp_buffer, 1, &bytes_transfered);316 &tmp_buffer, sizeof(tmp_buffer), &bytes_transfered); 320 317 if (rc != EOK) { 321 318 return rc; 322 319 } 323 320 if (bytes_transfered != 1) { 324 /* FIXME: some better error code? */ 325 return ESTALL; 326 } 327 328 size_t size = tmp_buffer[0]; 321 return ELIMIT; 322 } 323 324 const size_t size = tmp_buffer; 329 325 if (size == 0) { 330 /* FIXME: some better error code? */ 331 return ESTALL; 326 return ELIMIT; 332 327 } 333 328 … … 349 344 if (bytes_transfered != size) { 350 345 free(buffer); 351 /* FIXME: some better error code? */ 352 return ESTALL; 346 return ELIMIT; 353 347 } 354 348 … … 378 372 int rc = usb_request_get_descriptor(pipe, 379 373 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 380 USB_DESCTYPE_DEVICE, 0, 0, 381 &descriptor_tmp, sizeof(descriptor_tmp), 374 USB_DESCTYPE_DEVICE, 0, 0, &descriptor_tmp, sizeof(descriptor_tmp), 382 375 &actually_transferred); 383 376 … … 421 414 size_t actually_transferred = 0; 422 415 usb_standard_configuration_descriptor_t descriptor_tmp; 423 int rc = usb_request_get_descriptor(pipe,416 const int rc = usb_request_get_descriptor(pipe, 424 417 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 425 418 USB_DESCTYPE_CONFIGURATION, index, 0, … … 479 472 int usb_request_get_full_configuration_descriptor_alloc( 480 473 usb_pipe_t *pipe, int index, 481 void **descriptor_ptr, size_t *descriptor_size)474 const void **descriptor_ptr, size_t *descriptor_size) 482 475 { 483 476 int rc; … … 546 539 usb_request_type_t request_type, usb_request_recipient_t recipient, 547 540 uint8_t descriptor_type, uint8_t descriptor_index, 548 uint16_t language, 549 void *buffer, size_t size) 541 uint16_t language, const void *buffer, size_t size) 550 542 { 551 543 if (buffer == NULL) { … … 560 552 561 553 return usb_control_request_set(pipe, 562 request_type, recipient, 563 USB_DEVREQ_SET_DESCRIPTOR, 564 wValue, language, 565 buffer, size); 554 request_type, recipient, USB_DEVREQ_SET_DESCRIPTOR, 555 wValue, language, buffer, size); 566 556 } 567 557 … … 578 568 size_t actual_size; 579 569 580 int rc = usb_control_request_get(pipe,570 const int rc = usb_control_request_get(pipe, 581 571 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 582 USB_DEVREQ_GET_CONFIGURATION, 583 0, 0, 584 &value, 1, &actual_size); 572 USB_DEVREQ_GET_CONFIGURATION, 0, 0, &value, 1, &actual_size); 585 573 586 574 if (rc != EOK) { … … 607 595 uint8_t configuration_value) 608 596 { 609 uint16_t config_value597 const uint16_t config_value 610 598 = uint16_host2usb((uint16_t) configuration_value); 611 599 … … 629 617 size_t actual_size; 630 618 631 int rc = usb_control_request_get(pipe,619 const int rc = usb_control_request_get(pipe, 632 620 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE, 633 621 USB_DEVREQ_GET_INTERFACE, 634 622 0, uint16_host2usb((uint16_t) interface_index), 635 &value, 1, &actual_size);623 &value, sizeof(value), &actual_size); 636 624 637 625 if (rc != EOK) { … … 678 666 l18_win_locales_t **languages_ptr, size_t *languages_count) 679 667 { 680 int rc; 681 682 if (languages_ptr == NULL) { 683 return EBADMEM; 684 } 685 if (languages_count == NULL) { 668 if (languages_ptr == NULL || languages_count == NULL) { 686 669 return EBADMEM; 687 670 } … … 689 672 uint8_t *string_descriptor = NULL; 690 673 size_t string_descriptor_size = 0; 691 rc = usb_request_get_descriptor_alloc(pipe,674 const int rc = usb_request_get_descriptor_alloc(pipe, 692 675 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 693 676 USB_DESCTYPE_STRING, 0, 0, … … 710 693 } 711 694 712 size_t langs_count = string_descriptor_size / 2;713 l18_win_locales_t *langs 714 = malloc(sizeof(l18_win_locales_t) * langs_count);695 const size_t langs_count = string_descriptor_size / 2; 696 l18_win_locales_t *langs = 697 calloc(langs_count, sizeof(l18_win_locales_t)); 715 698 if (langs == NULL) { 716 699 free(string_descriptor); … … 718 701 } 719 702 720 size_t i; 721 for (i = 0; i < langs_count; i++) { 703 for (size_t i = 0; i < langs_count; i++) { 722 704 /* Language code from the descriptor is in USB endianness. */ 723 705 /* FIXME: is this really correct? */ 724 uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8) 706 const uint16_t lang_code = 707 (string_descriptor[2 + 2 * i + 1] << 8) 725 708 + string_descriptor[2 + 2 * i]; 726 709 langs[i] = uint16_usb2host(lang_code); … … 761 744 } 762 745 /* Language is actually two byte value. */ 763 if (lang > 0xFFFF) {746 if (lang > L18N_WIN_LOCALE_MAX) { 764 747 return ERANGE; 765 748 } … … 795 778 } 796 779 797 size_t string_char_count = string_size / 2;780 const size_t string_char_count = string_size / 2; 798 781 string_chars = malloc(sizeof(wchar_t) * (string_char_count + 1)); 799 782 if (string_chars == NULL) { … … 807 790 * do not have them). 808 791 */ 809 size_t i; 810 for (i = 0; i < string_char_count; i++) { 811 uint16_t uni_char = (string[2 + 2 * i + 1] << 8) 792 for (size_t i = 0; i < string_char_count; i++) { 793 const uint16_t uni_char = (string[2 + 2 * i + 1] << 8) 812 794 + string[2 + 2 * i]; 813 795 string_chars[i] = uni_char; … … 827 809 828 810 leave: 829 if (string != NULL) { 830 free(string); 831 } 832 if (string_chars != NULL) { 833 free(string_chars); 834 } 811 free(string); 812 free(string_chars); 835 813 836 814 return rc; … … 847 825 return usb_request_clear_feature(pipe, 848 826 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT, 849 uint16_host2usb(USB_FEATURE_ SELECTOR_ENDPOINT_HALT),827 uint16_host2usb(USB_FEATURE_ENDPOINT_HALT), 850 828 uint16_host2usb(ep_index)); 851 829 } -
uspace/lib/usbhid/src/hidreport.c
r5b18137 rb4b534ac 61 61 62 62 usb_dp_parser_data_t parser_data = { 63 .data = dev->descriptors.configuration,64 .size = dev->descriptors.configuration_size,63 .data = usb_device_descriptors(dev)->full_config, 64 .size = usb_device_descriptors(dev)->full_config_size, 65 65 .arg = NULL 66 66 }; … … 71 71 const uint8_t *d = 72 72 usb_dp_get_nested_descriptor(&parser, &parser_data, 73 dev->descriptors.configuration);73 usb_device_descriptors(dev)->full_config); 74 74 75 75 /* … … 77 77 */ 78 78 int i = 0; 79 while (d != NULL && i < dev->interface_no) {79 while (d != NULL && i < usb_device_get_iface_number(dev)) { 80 80 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 81 dev->descriptors.configuration, d);81 usb_device_descriptors(dev)->full_config, d); 82 82 ++i; 83 83 } … … 85 85 if (d == NULL) { 86 86 usb_log_error("The %d. interface descriptor not found!\n", 87 dev->interface_no);87 usb_device_get_iface_number(dev)); 88 88 return ENOENT; 89 89 } … … 135 135 * Get the descriptor from the device. 136 136 */ 137 int rc = usb_request_get_descriptor( &dev->ctrl_pipe,137 int rc = usb_request_get_descriptor(usb_device_get_default_pipe(dev), 138 138 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE, 139 USB_DESCTYPE_HID_REPORT, 0, dev->interface_no,139 USB_DESCTYPE_HID_REPORT, 0, usb_device_get_iface_number(dev), 140 140 *report_desc, length, &actual_size); 141 141 -
uspace/lib/usbhid/src/hidreq.c
r5b18137 rb4b534ac 182 182 uint16_t value = duration << 8; 183 183 184 rc = usb_control_request_set(ctrl_pipe, 185 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 184 rc = usb_control_request_set(ctrl_pipe, 185 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 186 186 USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0); 187 187 188 188 if (rc != EOK) { 189 usb_log_warning(" Error sending Set Idle request to the device: "189 usb_log_warning("Device did not accept Set Idle request: " 190 190 "%s.\n", str_error(rc)); 191 191 return rc; -
uspace/lib/usbhost/Makefile
r5b18137 rb4b534ac 32 32 -I$(LIBUSB_PREFIX)/include \ 33 33 -I$(LIBDRV_PREFIX)/include \ 34 -Iinclude/usb/host \ 34 35 -Iinclude 35 36 36 37 SOURCES = \ 38 src/ddf_helpers.c \ 37 39 src/endpoint.c \ 38 src/iface.c \ 39 src/usb_device_manager.c \ 40 src/usb_endpoint_manager.c \ 40 src/hcd.c \ 41 src/usb_bus.c \ 41 42 src/usb_transfer_batch.c 42 43 -
uspace/lib/usbhost/include/usb/host/ddf_helpers.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 1 Vojtech Horky2 * Copyright (c) 2012 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbohci 28 29 /** @addtogroup libusbhost 29 30 * @{ 30 31 */ 31 32 /** @file 32 * PCI related functions needed by OHCI driver.33 * 33 34 */ 34 #ifndef DRV_OHCI_RES_H 35 #define DRV_OHCI_RES_H 35 36 #ifndef LIBUSBHOST_HOST_DDF_HELPERS_H 37 #define LIBUSBHOST_HOST_DDF_HELPERS_H 38 39 #include <usb/host/hcd.h> 40 #include <usb/host/usb_bus.h> 41 #include <usb/usb.h> 36 42 37 43 #include <ddf/driver.h> 44 #include <ddf/interrupt.h> 38 45 #include <device/hw_res_parsed.h> 39 46 40 int get_my_registers(ddf_dev_t *, addr_range_t *, int *); 41 int enable_interrupts(ddf_dev_t *); 47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool); 48 typedef void (*driver_fini_t)(hcd_t *); 49 typedef int (*claim_t)(ddf_dev_t *); 50 typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *); 51 52 typedef struct { 53 hcd_ops_t ops; 54 claim_t claim; 55 usb_speed_t hc_speed; 56 driver_init_t init; 57 driver_fini_t fini; 58 interrupt_handler_t *irq_handler; 59 irq_code_gen_t irq_code_gen; 60 const char *name; 61 } ddf_hc_driver_t; 62 63 int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver); 64 65 int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed, 66 size_t bw, bw_count_func_t bw_count); 67 void hcd_ddf_clean_hc(ddf_dev_t *device); 68 int hcd_ddf_setup_root_hub(ddf_dev_t *device); 69 70 hcd_t *dev_to_hcd(ddf_dev_t *dev); 71 72 int hcd_ddf_enable_interrupts(ddf_dev_t *device); 73 int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res); 74 int hcd_ddf_setup_interrupts(ddf_dev_t *device, 75 const hw_res_list_parsed_t *hw_res, 76 interrupt_handler_t handler, 77 int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *)); 78 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev); 42 79 43 80 #endif 81 44 82 /** 45 83 * @} 46 84 */ 47 -
uspace/lib/usbhost/include/usb/host/endpoint.h
r5b18137 rb4b534ac 57 57 /** Maximum size of data packets. */ 58 58 size_t max_packet_size; 59 /** Additional opportunities per uframe */ 60 unsigned packets; 59 61 /** Necessary bandwidth. */ 60 62 size_t bandwidth; … … 67 69 /** Signals change of active status. */ 68 70 fibril_condvar_t avail; 71 /** High speed TT data */ 72 struct { 73 usb_address_t address; 74 unsigned port; 75 } tt; 69 76 /** Optional device specific data. */ 70 77 struct { … … 80 87 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 81 88 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 82 size_t max_packet_size, size_t bw); 89 size_t max_packet_size, unsigned packets, size_t bw, 90 usb_address_t tt_address, unsigned tt_port); 83 91 void endpoint_destroy(endpoint_t *instance); 84 92 -
uspace/lib/usbhost/include/usb/host/hcd.h
r5b18137 rb4b534ac 37 37 #define LIBUSBHOST_HOST_HCD_H 38 38 39 #include <usb/host/endpoint.h> 40 #include <usb/host/usb_bus.h> 41 #include <usb/host/usb_transfer_batch.h> 42 #include <usb/usb.h> 43 39 44 #include <assert.h> 40 45 #include <usbhc_iface.h> 41 42 #include <usb/host/usb_device_manager.h> 43 #include <usb/host/usb_endpoint_manager.h> 44 #include <usb/host/usb_transfer_batch.h> 46 #include <sys/types.h> 45 47 46 48 typedef struct hcd hcd_t; 47 49 50 typedef int (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *); 51 typedef int (*ep_add_hook_t)(hcd_t *, endpoint_t *); 52 typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *); 53 typedef void (*interrupt_hook_t)(hcd_t *, uint32_t); 54 typedef int (*status_hook_t)(hcd_t *, uint32_t *); 55 56 typedef struct { 57 /** Transfer scheduling, implement in device driver. */ 58 schedule_hook_t schedule; 59 /** Hook called upon registering new endpoint. */ 60 ep_add_hook_t ep_add_hook; 61 /** Hook called upon removing of an endpoint. */ 62 ep_remove_hook_t ep_remove_hook; 63 /** Hook to be called on device interrupt, passes ARG1 */ 64 interrupt_hook_t irq_hook; 65 /** Periodic polling hook */ 66 status_hook_t status_hook; 67 } hcd_ops_t; 68 48 69 /** Generic host controller driver structure. */ 49 70 struct hcd { 50 /** Device manager storing handles and addresses. */51 usb_device_manager_t dev_manager;52 71 /** Endpoint manager. */ 53 usb_ endpoint_manager_t ep_manager;72 usb_bus_t bus; 54 73 74 /** Interrupt replacement fibril */ 75 fid_t polling_fibril; 76 77 /** Driver implementation */ 78 hcd_ops_t ops; 55 79 /** Device specific driver data. */ 56 void *private_data; 57 /** Transfer scheduling, implement in device driver. */ 58 int (*schedule)(hcd_t *, usb_transfer_batch_t *); 59 /** Hook called upon registering new endpoint. */ 60 int (*ep_add_hook)(hcd_t *, endpoint_t *); 61 /** Hook called upon removing of an endpoint. */ 62 void (*ep_remove_hook)(hcd_t *, endpoint_t *); 80 void * driver_data; 63 81 }; 64 82 65 /** Initialize hcd_t structure. 66 * Initializes device and endpoint managers. Sets data and hook pointer to NULL. 67 * @param hcd hcd_t structure to initialize, non-null. 68 * @param bandwidth Available bandwidth, passed to endpoint manager. 69 * @param bw_count Bandwidth compute function, passed to endpoint manager. 70 */ 71 static inline void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth, 72 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 83 void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth, 84 bw_count_func_t bw_count); 85 86 static inline void hcd_set_implementation(hcd_t *hcd, void *data, 87 const hcd_ops_t *ops) 73 88 { 74 89 assert(hcd); 75 usb_device_manager_init(&hcd->dev_manager, max_speed);76 usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);77 hcd->private_data = NULL;78 hcd->schedule = NULL;79 hcd->ep_add_hook = NULL;80 hcd->ep_remove_hook = NULL;90 if (ops) { 91 hcd->driver_data = data; 92 hcd->ops = *ops; 93 } else { 94 memset(&hcd->ops, 0, sizeof(hcd->ops)); 95 } 81 96 } 82 97 83 /** Check registered endpoints and reset toggle bit if necessary. 84 * @param hcd hcd_t structure, non-null. 85 * @param target Control communication target. 86 * @param setup_data Setup packet of the control communication. 87 */ 88 static inline void reset_ep_if_need(hcd_t *hcd, usb_target_t target, 89 const char setup_data[8]) 98 static inline void * hcd_get_driver_data(hcd_t *hcd) 90 99 { 91 100 assert(hcd); 92 usb_endpoint_manager_reset_eps_if_need( 93 &hcd->ep_manager, target, (const uint8_t *)setup_data); 101 return hcd->driver_data; 94 102 } 95 103 96 /** Data retrieve wrapper. 97 * @param fun ddf function, non-null. 98 * @return pointer cast to hcd_t*. 99 */ 100 static inline hcd_t *fun_to_hcd(ddf_fun_t *fun) 104 usb_address_t hcd_request_address(hcd_t *hcd, usb_speed_t speed); 105 106 int hcd_release_address(hcd_t *hcd, usb_address_t address); 107 108 int hcd_reserve_default_address(hcd_t *hcd, usb_speed_t speed); 109 110 static inline int hcd_release_default_address(hcd_t *hcd) 101 111 { 102 return ddf_fun_data_get(fun);112 return hcd_release_address(hcd, USB_ADDRESS_DEFAULT); 103 113 } 104 114 105 extern usbhc_iface_t hcd_iface; 115 int hcd_add_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir, 116 usb_transfer_type_t type, size_t max_packet_size, unsigned packets, 117 size_t size, usb_address_t tt_address, unsigned tt_port); 118 119 int hcd_remove_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir); 120 121 int hcd_send_batch(hcd_t *hcd, usb_target_t target, usb_direction_t direction, 122 void *data, size_t size, uint64_t setup_data, 123 usbhc_iface_transfer_in_callback_t in, 124 usbhc_iface_transfer_out_callback_t out, void *arg, const char* name); 125 126 ssize_t hcd_send_batch_sync(hcd_t *hcd, usb_target_t target, 127 usb_direction_t dir, void *data, size_t size, uint64_t setup_data, 128 const char* name); 106 129 107 130 #endif 108 109 131 /** 110 132 * @} -
uspace/lib/usbhost/include/usb/host/usb_bus.h
r5b18137 rb4b534ac 40 40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 #include <usb/host/endpoint.h> 43 #include <usb/usb.h> 44 42 45 #include <adt/list.h> 43 46 #include <fibril_synch.h> 44 #include < usb/usb.h>47 #include <stdbool.h> 45 48 46 #include <usb/host/endpoint.h>47 49 48 50 /** Bytes per second in FULL SPEED */ … … 50 52 /** 90% of total bandwidth is available for periodic transfers */ 51 53 #define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9) 52 /** 16 addresses per list */ 53 #define ENDPOINT_LIST_COUNT 8 54 55 //TODO: Implement 56 #define BANDWIDTH_AVAILABLE_USB20 1 57 58 typedef size_t (*bw_count_func_t)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 59 typedef void (*ep_remove_callback_t)(endpoint_t *, void *); 60 typedef int (*ep_add_callback_t)(endpoint_t *, void *); 54 61 55 62 /** Endpoint management structure */ 56 typedef struct usb_endpoint_manager { 57 /** Store endpoint_t instances */ 58 list_t endpoint_lists[ENDPOINT_LIST_COUNT]; 63 typedef struct usb_bus { 64 struct { 65 usb_speed_t speed; /**< Device speed */ 66 bool occupied; /**< The address is in use. */ 67 list_t endpoint_list; /**< Store endpoint_t instances */ 68 } devices[USB_ADDRESS_COUNT]; 59 69 /** Prevents races accessing lists */ 60 70 fibril_mutex_t guard; … … 62 72 size_t free_bw; 63 73 /** Use this function to count bw required by EP */ 64 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 65 } usb_endpoint_manager_t; 74 bw_count_func_t bw_count; 75 /** Maximum speed allowed. */ 76 usb_speed_t max_speed; 77 /** The last reserved address */ 78 usb_address_t last_address; 79 } usb_bus_t; 80 66 81 67 82 size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type, 68 83 size_t size, size_t max_packet_size); 84 size_t bandwidth_count_usb20(usb_speed_t speed, usb_transfer_type_t type, 85 size_t size, size_t max_packet_size); 69 86 70 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 71 size_t available_bandwidth, 72 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)); 87 int usb_bus_init(usb_bus_t *instance, 88 size_t available_bandwidth, bw_count_func_t bw_count, usb_speed_t max_speed); 73 89 74 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, 75 usb_target_t target, const uint8_t data[8]); 90 int usb_bus_register_ep(usb_bus_t *instance, endpoint_t *ep, size_t data_size); 76 91 77 int usb_endpoint_manager_register_ep( 78 usb_endpoint_manager_t *instance, endpoint_t *ep, size_t data_size); 79 int usb_endpoint_manager_unregister_ep( 80 usb_endpoint_manager_t *instance, endpoint_t *ep); 81 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance, 92 int usb_bus_unregister_ep(usb_bus_t *instance, endpoint_t *ep); 93 94 endpoint_t * usb_bus_find_ep(usb_bus_t *instance, 82 95 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction); 83 96 84 int usb_ endpoint_manager_add_ep(usb_endpoint_manager_t *instance,97 int usb_bus_add_ep(usb_bus_t *instance, 85 98 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 86 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 87 size_t data_size, int (*callback)(endpoint_t *, void *), void *arg); 99 usb_transfer_type_t type, size_t max_packet_size, unsigned packets, 100 size_t data_size, ep_add_callback_t callback, void *arg, 101 usb_address_t tt_address, unsigned tt_port); 88 102 89 int usb_ endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,103 int usb_bus_remove_ep(usb_bus_t *instance, 90 104 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 91 void (*callback)(endpoint_t *, void *), void *arg);105 ep_remove_callback_t callback, void *arg); 92 106 93 void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance, 94 usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg); 107 int usb_bus_reset_toggle(usb_bus_t *instance, usb_target_t target, bool all); 108 109 int usb_bus_remove_address(usb_bus_t *instance, 110 usb_address_t address, ep_remove_callback_t callback, void *arg); 111 112 int usb_bus_request_address(usb_bus_t *instance, 113 usb_address_t *address, bool strict, usb_speed_t speed); 114 115 int usb_bus_get_speed(usb_bus_t *instance, 116 usb_address_t address, usb_speed_t *speed); 95 117 #endif 96 118 /** -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
r5b18137 rb4b534ac 37 37 #define LIBUSBHOST_HOST_USB_TRANSFER_BATCH_H 38 38 39 #include <adt/list.h> 39 #include <usb/host/endpoint.h> 40 #include <usb/usb.h> 40 41 42 #include <assert.h> 43 #include <stdbool.h> 44 #include <sys/types.h> 41 45 #include <usbhc_iface.h> 42 #include <usb/usb.h>43 #include <usb/host/endpoint.h>44 46 45 47 #define USB_SETUP_PACKET_SIZE 8 … … 67 69 */ 68 70 size_t setup_size; 69 /** Host controller function, passed to callback function */70 ddf_fun_t *fun;71 71 72 72 /** Actually used portion of the buffer … … 80 80 */ 81 81 int error; 82 83 /** Driver specific data */84 void *private_data;85 /** Callback to properly remove driver data during destruction */86 void (*private_data_dtor)(void *p_data);87 82 } usb_transfer_batch_t; 88 83 … … 108 103 usbhc_iface_transfer_in_callback_t func_in, 109 104 usbhc_iface_transfer_out_callback_t func_out, 110 void *arg, 111 ddf_fun_t *fun, 112 void *private_data, 113 void (*private_data_dtor)(void *p_data) 105 void *arg 114 106 ); 115 107 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); -
uspace/lib/usbhost/include/usb/host/utils/malloc32.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusb ohci28 /** @addtogroup drvusbehci 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief OHCI driver32 * @brief EHCI driver 33 33 */ 34 #ifndef DRV_ OHCI_UTILS_MALLOC32_H35 #define DRV_ OHCI_UTILS_MALLOC32_H34 #ifndef DRV_EHCI_UTILS_MALLOC32_H 35 #define DRV_EHCI_UTILS_MALLOC32_H 36 36 37 #include <a ssert.h>38 #include < malloc.h>39 #include < unistd.h>37 #include <align.h> 38 #include <as.h> 39 #include <ddi.h> 40 40 #include <errno.h> 41 #include < mem.h>42 #include < as.h>41 #include <stdlib.h> 42 #include <sys/types.h> 43 43 44 44 /* Generic TDs and EDs require 16byte alignment, … … 46 46 * buffers do not have to be aligned. 47 47 */ 48 #define OHCI_ALIGN 32 48 #define EHCI_ALIGN 32 49 50 #define EHCI_REQUIRED_PAGE_SIZE 4096 49 51 50 52 /** Get physical address translation … … 70 72 */ 71 73 static inline void * malloc32(size_t size) 72 { return memalign(OHCI_ALIGN, size); } 74 { 75 uintptr_t phys; 76 void *address = AS_AREA_ANY; 77 size_t real_size = ALIGN_UP(size, PAGE_SIZE); 78 79 const int ret = dmamem_map_anonymous(real_size, 80 DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0, &phys, 81 &address); 82 83 if (ret == EOK) { 84 /* Poison, accessing it should be enough to make sure 85 * the location is mapped, but poison works better */ 86 memset(address, 0x5, real_size); 87 return address; 88 } 89 return NULL; 90 } 73 91 74 92 /** Physical mallocator simulator … … 77 95 */ 78 96 static inline void free32(void *addr) 79 { free(addr); } 97 { 98 dmamem_unmap_anonymous(addr); 99 } 100 101 /** Create 4KB page mapping 102 * 103 * @return Address of the mapped page, NULL on failure. 104 */ 105 static inline void *get_page() 106 { 107 return malloc32(PAGE_SIZE); 108 } 109 110 static inline void return_page(void *page) 111 { 112 free32(page); 113 } 114 115 80 116 #endif 81 117 /** -
uspace/lib/usbhost/src/endpoint.c
r5b18137 rb4b534ac 33 33 */ 34 34 35 #include <usb/host/endpoint.h> 36 35 37 #include <assert.h> 36 38 #include <stdlib.h> 37 #include <errno.h>38 #include <usb/host/endpoint.h>39 39 40 40 /** Allocate ad initialize endpoint_t structure. … … 50 50 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 51 51 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 52 size_t max_packet_size, size_t bw) 52 size_t max_packet_size, unsigned packets, size_t bw, 53 usb_address_t tt_address, unsigned tt_p) 53 54 { 54 55 endpoint_t *instance = malloc(sizeof(endpoint_t)); … … 60 61 instance->speed = speed; 61 62 instance->max_packet_size = max_packet_size; 63 instance->packets = packets; 62 64 instance->bandwidth = bw; 63 65 instance->toggle = 0; 64 66 instance->active = false; 67 instance->tt.address = tt_address; 68 instance->tt.port = tt_p; 65 69 instance->hc_data.data = NULL; 66 70 instance->hc_data.toggle_get = NULL; … … 109 113 { 110 114 assert(instance); 111 fibril_mutex_lock(&instance->guard); 112 instance->hc_data.data = NULL; 113 instance->hc_data.toggle_get = NULL; 114 instance->hc_data.toggle_set = NULL; 115 fibril_mutex_unlock(&instance->guard); 115 endpoint_set_hc_data(instance, NULL, NULL, NULL); 116 116 } 117 117 -
uspace/lib/usbhost/src/usb_bus.c
r5b18137 rb4b534ac 33 33 */ 34 34 35 #include <stdbool.h> 35 #include <usb/host/usb_bus.h> 36 #include <usb/debug.h> 37 36 38 #include <assert.h> 37 39 #include <errno.h> 38 39 #include < usb/debug.h>40 #include <usb/host/usb_endpoint_manager.h> 40 #include <macros.h> 41 #include <stdbool.h> 42 41 43 42 44 /** Endpoint compare helper function. … … 63 65 64 66 /** Get list that holds endpoints for given address. 65 * @param instance usb_ endpoint_managerstructure, non-null.67 * @param instance usb_bus structure, non-null. 66 68 * @param addr USB address, must be >= 0. 67 69 * @return Pointer to the appropriate list. 68 70 */ 69 static list_t * get_list(usb_ endpoint_manager_t *instance, usb_address_t addr)71 static list_t * get_list(usb_bus_t *instance, usb_address_t addr) 70 72 { 71 73 assert(instance); 72 74 assert(addr >= 0); 73 return &instance-> endpoint_lists[addr % ENDPOINT_LIST_COUNT];75 return &instance->devices[addr % ARRAY_SIZE(instance->devices)].endpoint_list; 74 76 } 75 77 76 78 /** Internal search function, works on locked structure. 77 * @param instance usb_ endpoint_managerstructure, non-null.79 * @param instance usb_bus structure, non-null. 78 80 * @param address USB address, must be valid. 79 81 * @param endpoint USB endpoint number. … … 83 85 * @note Assumes that the internal mutex is locked. 84 86 */ 85 static endpoint_t * find_locked(usb_ endpoint_manager_t *instance,87 static endpoint_t * find_locked(usb_bus_t *instance, 86 88 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 87 89 { … … 95 97 } 96 98 return NULL; 99 } 100 101 /** Get a free USB address 102 * 103 * @param[in] instance Device manager structure to use. 104 * @return Free address, or error code. 105 */ 106 static usb_address_t usb_bus_get_free_address(usb_bus_t *instance) 107 { 108 109 usb_address_t new_address = instance->last_address; 110 do { 111 new_address = (new_address + 1) % USB_ADDRESS_COUNT; 112 if (new_address == USB_ADDRESS_DEFAULT) 113 new_address = 1; 114 if (new_address == instance->last_address) 115 return ENOSPC; 116 } while (instance->devices[new_address].occupied); 117 118 assert(new_address != USB_ADDRESS_DEFAULT); 119 instance->last_address = new_address; 120 121 return new_address; 97 122 } 98 123 … … 145 170 } 146 171 172 /** Calculate bandwidth that needs to be reserved for communication with EP. 173 * Calculation follows USB 2.0 specification. 174 * @param speed Device's speed. 175 * @param type Type of the transfer. 176 * @param size Number of byte to transfer. 177 * @param max_packet_size Maximum bytes in one packet. 178 */ 179 size_t bandwidth_count_usb20(usb_speed_t speed, usb_transfer_type_t type, 180 size_t size, size_t max_packet_size) 181 { 182 /* We care about bandwidth only for interrupt and isochronous. */ 183 if ((type != USB_TRANSFER_INTERRUPT) 184 && (type != USB_TRANSFER_ISOCHRONOUS)) { 185 return 0; 186 } 187 //TODO Implement 188 return 0; 189 } 190 147 191 /** Initialize to default state. 148 192 * You need to provide valid bw_count function if you plan to use 149 193 * add_endpoint/remove_endpoint pair. 150 194 * 151 * @param instance usb_ endpoint_managerstructure, non-null.195 * @param instance usb_bus structure, non-null. 152 196 * @param available_bandwidth Size of the bandwidth pool. 153 197 * @param bw_count function to use to calculate endpoint bw requirements. 154 198 * @return Error code. 155 199 */ 156 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 157 size_t available_bandwidth, 158 size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t)) 200 int usb_bus_init(usb_bus_t *instance, 201 size_t available_bandwidth, bw_count_func_t bw_count, usb_speed_t max_speed) 159 202 { 160 203 assert(instance); … … 162 205 instance->free_bw = available_bandwidth; 163 206 instance->bw_count = bw_count; 164 for (unsigned i = 0; i < ENDPOINT_LIST_COUNT; ++i) { 165 list_initialize(&instance->endpoint_lists[i]); 207 instance->last_address = 0; 208 instance->max_speed = max_speed; 209 for (unsigned i = 0; i < ARRAY_SIZE(instance->devices); ++i) { 210 list_initialize(&instance->devices[i].endpoint_list); 211 instance->devices[i].speed = USB_SPEED_MAX; 212 instance->devices[i].occupied = false; 166 213 } 167 214 return EOK; 168 }169 170 /** Check setup packet data for signs of toggle reset.171 *172 * @param[in] instance usb_endpoint_manager structure, non-null.173 * @param[in] target Device to receive setup packet.174 * @param[in] data Setup packet data.175 *176 * Really ugly one. Resets toggle bit on all endpoints that need it.177 * @TODO Use tools from libusbdev requests.h178 */179 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,180 usb_target_t target, const uint8_t data[8])181 {182 assert(instance);183 if (!usb_target_is_valid(target)) {184 usb_log_error("Invalid data when checking for toggle reset.\n");185 return;186 }187 188 assert(data);189 switch (data[1])190 {191 case 0x01: /* Clear Feature -- resets only cleared ep */192 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */193 // TODO Use macros in libusbdev requests.h194 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {195 fibril_mutex_lock(&instance->guard);196 /* endpoint number is < 16, thus first byte is enough */197 list_foreach(*get_list(instance, target.address),198 link, endpoint_t, ep) {199 if ((ep->address == target.address)200 && (ep->endpoint = data[4])) {201 endpoint_toggle_set(ep,0);202 }203 }204 fibril_mutex_unlock(&instance->guard);205 }206 break;207 208 case 0x9: /* Set Configuration */209 case 0x11: /* Set Interface */210 /* Recipient must be device, this resets all endpoints,211 * In fact there should be no endpoints but EP 0 registered212 * as different interfaces use different endpoints,213 * unless you're changing configuration or alternative214 * interface of an already setup device. */215 if ((data[0] & 0xf) == 0) {216 fibril_mutex_lock(&instance->guard);217 list_foreach(*get_list(instance, target.address),218 link, endpoint_t, ep) {219 if (ep->address == target.address) {220 endpoint_toggle_set(ep,0);221 }222 }223 fibril_mutex_unlock(&instance->guard);224 }225 break;226 }227 215 } 228 216 229 217 /** Register endpoint structure. 230 218 * Checks for duplicates. 231 * @param instance usb_ endpoint_manager, non-null.219 * @param instance usb_bus, non-null. 232 220 * @param ep endpoint_t to register. 233 221 * @param data_size Size of data to transfer. 234 222 * @return Error code. 235 223 */ 236 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 237 endpoint_t *ep, size_t data_size) 224 int usb_bus_register_ep(usb_bus_t *instance, endpoint_t *ep, size_t data_size) 238 225 { 239 226 assert(instance); … … 258 245 259 246 instance->free_bw -= ep->bandwidth; 247 usb_log_debug("Registered EP(%d:%d:%s:%s)\n", ep->address, ep->endpoint, 248 usb_str_transfer_type_short(ep->transfer_type), 249 usb_str_direction(ep->direction)); 260 250 fibril_mutex_unlock(&instance->guard); 261 251 return EOK; … … 264 254 /** Unregister endpoint structure. 265 255 * Checks for duplicates. 266 * @param instance usb_ endpoint_manager, non-null.256 * @param instance usb_bus, non-null. 267 257 * @param ep endpoint_t to unregister. 268 258 * @return Error code. 269 259 */ 270 int usb_endpoint_manager_unregister_ep( 271 usb_endpoint_manager_t *instance, endpoint_t *ep) 260 int usb_bus_unregister_ep(usb_bus_t *instance, endpoint_t *ep) 272 261 { 273 262 assert(instance); … … 282 271 list_remove(&ep->link); 283 272 instance->free_bw += ep->bandwidth; 273 usb_log_debug("Unregistered EP(%d:%d:%s:%s)\n", ep->address, 274 ep->endpoint, usb_str_transfer_type_short(ep->transfer_type), 275 usb_str_direction(ep->direction)); 284 276 fibril_mutex_unlock(&instance->guard); 285 277 return EOK; … … 287 279 288 280 /** Find endpoint_t representing the given communication route. 289 * @param instance usb_ endpoint_manager, non-null.281 * @param instance usb_bus, non-null. 290 282 * @param address 291 283 */ 292 endpoint_t * usb_ endpoint_manager_find_ep(usb_endpoint_manager_t *instance,284 endpoint_t * usb_bus_find_ep(usb_bus_t *instance, 293 285 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 294 286 { … … 302 294 303 295 /** Create and register new endpoint_t structure. 304 * @param instance usb_ endpoint_managerstructure, non-null.296 * @param instance usb_bus structure, non-null. 305 297 * @param address USB address. 306 298 * @param endpoint USB endpoint number. … … 314 306 * @return Error code. 315 307 */ 316 int usb_ endpoint_manager_add_ep(usb_endpoint_manager_t *instance,308 int usb_bus_add_ep(usb_bus_t *instance, 317 309 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 318 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size, 319 size_t data_size, int (*callback)(endpoint_t *, void *), void *arg) 310 usb_transfer_type_t type, size_t max_packet_size, unsigned packets, 311 size_t data_size, ep_add_callback_t callback, void *arg, 312 usb_address_t tt_address, unsigned tt_port) 320 313 { 321 314 assert(instance); 322 315 if (instance->bw_count == NULL) 323 316 return ENOTSUP; 324 if (address < 0) 325 return EINVAL; 326 327 const size_t bw = 328 instance->bw_count(speed, type, data_size, max_packet_size); 329 330 fibril_mutex_lock(&instance->guard); 331 /* Check for available bandwidth */ 332 if (bw > instance->free_bw) { 333 fibril_mutex_unlock(&instance->guard); 334 return ENOSPC; 317 if (!usb_address_is_valid(address)) 318 return EINVAL; 319 320 321 fibril_mutex_lock(&instance->guard); 322 /* Check for speed and address */ 323 if (!instance->devices[address].occupied) { 324 fibril_mutex_unlock(&instance->guard); 325 return ENOENT; 335 326 } 336 327 … … 342 333 } 343 334 344 ep = endpoint_create( 345 address, endpoint, direction, type, speed, max_packet_size, bw); 335 const usb_speed_t speed = instance->devices[address].speed; 336 const size_t bw = 337 instance->bw_count(speed, type, data_size, max_packet_size); 338 339 /* Check for available bandwidth */ 340 if (bw > instance->free_bw) { 341 fibril_mutex_unlock(&instance->guard); 342 return ENOSPC; 343 } 344 345 ep = endpoint_create(address, endpoint, direction, type, speed, 346 max_packet_size, packets, bw, tt_address, tt_port); 346 347 if (!ep) { 347 348 fibril_mutex_unlock(&instance->guard); … … 365 366 366 367 /** Unregister and destroy endpoint_t structure representing given route. 367 * @param instance usb_ endpoint_managerstructure, non-null.368 * @param instance usb_bus structure, non-null. 368 369 * @param address USB address. 369 370 * @param endpoint USB endpoint number. … … 373 374 * @return Error code. 374 375 */ 375 int usb_ endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,376 int usb_bus_remove_ep(usb_bus_t *instance, 376 377 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 377 void (*callback)(endpoint_t *, void *), void *arg)378 ep_remove_callback_t callback, void *arg) 378 379 { 379 380 assert(instance); … … 395 396 } 396 397 398 int usb_bus_reset_toggle(usb_bus_t *instance, usb_target_t target, bool all) 399 { 400 assert(instance); 401 if (!usb_target_is_valid(target)) 402 return EINVAL; 403 404 int ret = ENOENT; 405 406 fibril_mutex_lock(&instance->guard); 407 list_foreach(*get_list(instance, target.address), link, endpoint_t, ep) { 408 if ((ep->address == target.address) 409 && (all || ep->endpoint == target.endpoint)) { 410 endpoint_toggle_set(ep, 0); 411 ret = EOK; 412 } 413 } 414 fibril_mutex_unlock(&instance->guard); 415 return ret; 416 } 417 397 418 /** Unregister and destroy all endpoints using given address. 398 * @param instance usb_ endpoint_managerstructure, non-null.419 * @param instance usb_bus structure, non-null. 399 420 * @param address USB address. 400 421 * @param endpoint USB endpoint number. … … 404 425 * @return Error code. 405 426 */ 406 void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,407 usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg)408 { 409 list_t *list;410 link_t *link;411 link_t *next;412 413 assert(address >= 0);414 assert(instance); 415 fibril_mutex_lock(&instance->guard);416 417 list = get_list(instance, address); 418 li nk = list_first(list);419 while (link != NULL) {427 int usb_bus_remove_address(usb_bus_t *instance, 428 usb_address_t address, ep_remove_callback_t callback, void *arg) 429 { 430 assert(instance); 431 if (!usb_address_is_valid(address)) 432 return EINVAL; 433 434 fibril_mutex_lock(&instance->guard); 435 436 const int ret = instance->devices[address].occupied ? EOK : ENOENT; 437 instance->devices[address].occupied = false; 438 439 list_t *list = get_list(instance, address); 440 for (link_t *link = list_first(list); link != NULL; ) { 420 441 endpoint_t *ep = list_get_instance(link, endpoint_t, link); 421 next = list_next(link, list); 422 442 link = list_next(link, list); 423 443 if (ep->address == address) { 424 444 list_remove(&ep->link); … … 427 447 endpoint_destroy(ep); 428 448 } 429 link = next; 430 } 431 fibril_mutex_unlock(&instance->guard); 449 } 450 fibril_mutex_unlock(&instance->guard); 451 return ret; 452 } 453 454 /** Request USB address. 455 * @param instance usb_device_manager 456 * @param address Pointer to requested address value, place to store new address 457 * @parma strict Fail if the requested address is not available. 458 * @return Error code. 459 * @note Default address is only available in strict mode. 460 */ 461 int usb_bus_request_address(usb_bus_t *instance, 462 usb_address_t *address, bool strict, usb_speed_t speed) 463 { 464 assert(instance); 465 assert(address); 466 if (speed > instance->max_speed) 467 return ENOTSUP; 468 469 if (!usb_address_is_valid(*address)) 470 return EINVAL; 471 472 usb_address_t addr = *address; 473 474 fibril_mutex_lock(&instance->guard); 475 /* Only grant default address to strict requests */ 476 if ((addr == USB_ADDRESS_DEFAULT) && !strict) { 477 addr = usb_bus_get_free_address(instance); 478 } 479 480 if (instance->devices[addr].occupied) { 481 if (strict) { 482 fibril_mutex_unlock(&instance->guard); 483 return ENOENT; 484 } 485 addr = usb_bus_get_free_address(instance); 486 } 487 if (usb_address_is_valid(addr)) { 488 assert(instance->devices[addr].occupied == false); 489 assert(addr != USB_ADDRESS_DEFAULT || strict); 490 491 instance->devices[addr].occupied = true; 492 instance->devices[addr].speed = speed; 493 *address = addr; 494 addr = 0; 495 } 496 497 fibril_mutex_unlock(&instance->guard); 498 return addr; 499 } 500 501 /** Get speed assigned to USB address. 502 * 503 * @param[in] instance Device manager structure to use. 504 * @param[in] address Address the caller wants to find. 505 * @param[out] speed Assigned speed. 506 * @return Error code. 507 */ 508 int usb_bus_get_speed(usb_bus_t *instance, usb_address_t address, 509 usb_speed_t *speed) 510 { 511 assert(instance); 512 if (!usb_address_is_valid(address)) { 513 return EINVAL; 514 } 515 516 fibril_mutex_lock(&instance->guard); 517 518 const int ret = instance->devices[address].occupied ? EOK : ENOENT; 519 if (speed && instance->devices[address].occupied) { 520 *speed = instance->devices[address].speed; 521 } 522 523 fibril_mutex_unlock(&instance->guard); 524 return ret; 432 525 } 433 526 /** -
uspace/lib/usbhost/src/usb_transfer_batch.c
r5b18137 rb4b534ac 32 32 * USB transfer transaction structures (implementation). 33 33 */ 34 35 #include <usb/host/usb_transfer_batch.h> 36 #include <usb/debug.h> 37 38 #include <assert.h> 34 39 #include <errno.h> 35 40 #include <macros.h> 36 37 #include <usb/usb.h> 38 #include <usb/debug.h> 39 40 #include <usb/host/usb_transfer_batch.h> 41 #include <usb/host/hcd.h> 41 #include <mem.h> 42 #include <stdlib.h> 43 #include <usbhc_iface.h> 42 44 43 45 /** Allocate and initialize usb_transfer_batch structure. … … 61 63 usbhc_iface_transfer_in_callback_t func_in, 62 64 usbhc_iface_transfer_out_callback_t func_out, 63 void *arg, 64 ddf_fun_t *fun, 65 void *private_data, 66 void (*private_data_dtor)(void *) 65 void *arg 67 66 ) 68 67 { … … 81 80 instance->buffer_size = buffer_size; 82 81 instance->setup_size = 0; 83 instance->fun = fun;84 instance->private_data = private_data;85 instance->private_data_dtor = private_data_dtor;86 82 instance->transfered_size = 0; 87 83 instance->error = EOK; … … 110 106 endpoint_release(instance->ep); 111 107 } 112 if (instance->private_data) {113 assert(instance->private_data_dtor);114 instance->private_data_dtor(instance->private_data);115 }116 108 free(instance); 117 109 } … … 133 125 /* NOTE: Only one of these pointers should be set. */ 134 126 if (instance->callback_out) { 135 /* Check for commands that reset toggle bit */ 136 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 137 && error == EOK) { 138 const usb_target_t target = 139 {{ instance->ep->address, instance->ep->endpoint }}; 140 reset_ep_if_need(fun_to_hcd(instance->fun), target, 141 instance->setup_buffer); 142 } 143 instance->callback_out(instance->fun, error, instance->arg); 127 instance->callback_out(error, instance->arg); 144 128 } 145 129 … … 150 134 memcpy(instance->buffer, data, safe_size); 151 135 } 152 instance->callback_in(instance->fun, error, 153 safe_size, instance->arg); 136 instance->callback_in(error, safe_size, instance->arg); 154 137 } 155 138 } -
uspace/lib/usbvirt/Makefile
r5b18137 rb4b534ac 34 34 -I$(LIBUSB_PREFIX)/include \ 35 35 -I$(LIBUSBDEV_PREFIX)/include \ 36 -Iinclude 36 -Iinclude \ 37 -Iinclude/usbvirt 37 38 38 39 SOURCES = \ … … 42 43 src/ipc_hc.c \ 43 44 src/stdreq.c \ 44 src/transfer.c 45 src/transfer.c \ 46 src/virthub_base.c \ 47 src/virthub_descriptors.c 45 48 46 49 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/usbvirt/include/usbvirt/device.h
r5b18137 rb4b534ac 40 40 #include <usb/dev/request.h> 41 41 #include <async.h> 42 #include <errno.h> 43 42 44 43 45 /** Maximum number of endpoints supported by virtual USB. */ … … 57 59 typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *dev, 58 60 usb_endpoint_t endpoint, usb_transfer_type_t transfer_type, 59 void *buffer, size_t buffer_size);61 const void *buffer, size_t buffer_size); 60 62 61 63 /** Callback for data from device (IN transaction). … … 88 90 uint8_t *data, size_t *act_data_size); 89 91 92 /** Create a class request to get data from device 93 * 94 * @param rec Request recipient. 95 * @param req Request code. 96 */ 97 #define CLASS_REQ_IN(rec, req) \ 98 .request_type = SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_CLASS, rec), \ 99 .request = req 100 101 /** Create a class request to send data to device 102 * 103 * @param rec Request recipient. 104 * @param req Request code. 105 */ 106 #define CLASS_REQ_OUT(rec, req) \ 107 .request_type = SETUP_REQUEST_TO_DEVICE(USB_REQUEST_TYPE_CLASS, rec), \ 108 .request = req 109 110 /** Create a standard request to get data from device 111 * 112 * @param rec Request recipient. 113 * @param req Request code. 114 */ 115 #define STD_REQ_IN(rec, req) \ 116 .request_type = SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, rec), \ 117 .request = req 118 119 /** Create a standard request to send data to device 120 * 121 * @param rec Request recipient. 122 * @param req Request code. 123 */ 124 #define STD_REQ_OUT(rec, req) \ 125 .request_type = SETUP_REQUEST_TO_DEVICE(USB_REQUEST_TYPE_STANDARD, rec), \ 126 .request = req 127 90 128 /** Callback for control request on a virtual USB device. 91 129 * … … 94 132 */ 95 133 typedef struct { 96 /** Request direction (in or out). */ 97 usb_direction_t req_direction; 98 /** Request recipient (device, interface or endpoint). */ 99 usb_request_recipient_t req_recipient; 100 /** Request type (standard, class or vendor). */ 101 usb_request_type_t req_type; 134 /* Request type. See usb/request.h */ 135 uint8_t request_type; 102 136 /** Actual request code. */ 103 137 uint8_t request; … … 111 145 typedef struct { 112 146 /** Actual data. */ 113 uint8_t *data;147 const uint8_t *data; 114 148 /** Data length. */ 115 149 size_t length; … … 121 155 usb_standard_configuration_descriptor_t *descriptor; 122 156 /** Array of extra data. */ 123 usbvirt_device_configuration_extras_t *extra;157 const usbvirt_device_configuration_extras_t *extra; 124 158 /** Length of @c extra array. */ 125 159 size_t extra_count; … … 131 165 * There is always only one such descriptor for the device. 132 166 */ 133 usb_standard_device_descriptor_t *device;167 const usb_standard_device_descriptor_t *device; 134 168 135 169 /** Configurations. */ … … 164 198 * Last handler is expected to have the @c callback field set to NULL 165 199 */ 166 usbvirt_control_request_handler_t *control;200 const usbvirt_control_request_handler_t *control; 167 201 /** Callback when device changes state. 168 202 * … … 180 214 /** Virtual USB device. */ 181 215 struct usbvirt_device { 216 /** Device does not require USB bus power */ 217 bool self_powered; 218 /** Device is allowed to signal remote wakeup */ 219 bool remote_wakeup; 182 220 /** Name for debugging purposes. */ 183 221 const char *name; … … 187 225 usbvirt_device_ops_t *ops; 188 226 /** Device descriptors. */ 189 usbvirt_descriptors_t *descriptors;227 const usbvirt_descriptors_t *descriptors; 190 228 /** Current device address. 191 229 * You shall treat this field as read only in your code. … … 202 240 }; 203 241 242 243 int req_nop(usbvirt_device_t *device, 244 const usb_device_request_setup_packet_t *setup_packet, 245 uint8_t *data, size_t *act_size); 246 204 247 int usbvirt_device_plug(usbvirt_device_t *, const char *); 205 248 void usbvirt_device_unplug(usbvirt_device_t *); 206 249 207 250 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *, 208 uint8_t *, size_t *, void *, size_t);209 210 int usbvirt_control_write(usbvirt_device_t *, void *, size_t, void *, size_t);211 int usbvirt_control_read(usbvirt_device_t *, void *, size_t, void *, size_t, size_t *);251 uint8_t *, size_t *, const void *, size_t); 252 253 int usbvirt_control_write(usbvirt_device_t *, const void *, size_t, void *, size_t); 254 int usbvirt_control_read(usbvirt_device_t *, const void *, size_t, void *, size_t, size_t *); 212 255 int usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t, 213 void *, size_t);256 const void *, size_t); 214 257 int usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t, 215 258 void *, size_t, size_t *); -
uspace/lib/usbvirt/include/usbvirt/virthub_base.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup drvusbvhc29 /** @addtogroup libusbvirt 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief Virtual USB hub.33 * Virtual USB device. 34 34 */ 35 35 36 #ifndef VHCD_HUB_H_37 #define VHCD_HUB_H_36 #ifndef LIBUSBVIRT_VIRTHUB_BASE_H_ 37 #define LIBUSBVIRT_VIRTHUB_BASE_H_ 38 38 39 39 #include <usbvirt/device.h> 40 #include < ddf/driver.h>40 #include <usb/classes/hub.h> 41 41 42 #include "hub/hub.h" 43 #include "hub/virthub.h" 42 enum { 43 VIRTHUB_EXTR_DESC = 3, 44 }; 44 45 45 extern usbvirt_device_t virtual_hub_device; 46 typedef struct { 47 usb_standard_configuration_descriptor_t config_descriptor; 48 usb_standard_endpoint_descriptor_t endpoint_descriptor; 49 usbvirt_device_configuration_extras_t extra[VIRTHUB_EXTR_DESC]; 50 usbvirt_device_configuration_t configuration; 51 usbvirt_descriptors_t descriptors; 52 usbvirt_device_t device; 53 void *data; 54 } virthub_base_t; 46 55 47 void virtual_hub_device_init(ddf_fun_t *); 56 void *virthub_get_data(usbvirt_device_t *dev); 57 58 int virthub_base_init(virthub_base_t *instance, 59 const char *name, usbvirt_device_ops_t *ops, void *data, 60 const usb_standard_device_descriptor_t *device_desc, 61 const usb_hub_descriptor_header_t *hub_desc, usb_endpoint_t ep); 62 63 usb_address_t virthub_base_get_address(virthub_base_t *instance); 64 65 int virthub_base_request(virthub_base_t *instance, usb_target_t target, 66 usb_direction_t dir, const usb_device_request_setup_packet_t *setup, 67 void *buffer, size_t buffer_size, size_t *real_size); 68 69 int virthub_base_get_hub_descriptor(usbvirt_device_t *dev, 70 const usb_device_request_setup_packet_t *request, uint8_t *data, 71 size_t *act_size); 72 int virthub_base_get_null_status(usbvirt_device_t *dev, 73 const usb_device_request_setup_packet_t *request, uint8_t *data, 74 size_t *act_size); 75 48 76 49 77 #endif 78 50 79 /** 51 80 * @} -
uspace/lib/usbvirt/src/ctrltransfer.c
r5b18137 rb4b534ac 50 50 */ 51 51 int process_control_transfer(usbvirt_device_t *dev, 52 usbvirt_control_request_handler_t *control_handlers,53 usb_device_request_setup_packet_t *setup,52 const usbvirt_control_request_handler_t *control_handlers, 53 const usb_device_request_setup_packet_t *setup, 54 54 uint8_t *data, size_t *data_sent_size) 55 55 { … … 60 60 return EFORWARD; 61 61 } 62 63 usb_direction_t direction = setup->request_type & 128 ? 64 USB_DIRECTION_IN : USB_DIRECTION_OUT; 65 usb_request_recipient_t req_recipient = setup->request_type & 31; 66 usb_request_type_t req_type = (setup->request_type >> 5) & 3; 67 68 usbvirt_control_request_handler_t *handler = control_handlers; 69 while (handler->callback != NULL) { 70 if (handler->req_direction != direction) { 71 goto next; 72 } 73 if (handler->req_recipient != req_recipient) { 74 goto next; 75 } 76 if (handler->req_type != req_type) { 77 goto next; 78 } 79 if (handler->request != setup->request) { 80 goto next; 62 const usbvirt_control_request_handler_t *handler = control_handlers; 63 for (;handler->callback != NULL; ++handler) { 64 if (handler->request != setup->request || 65 handler->request_type != setup->request_type) { 66 continue; 81 67 } 82 68 … … 84 70 usb_debug_str_buffer((uint8_t*) setup, sizeof(*setup), 0)); 85 71 int rc = handler->callback(dev, setup, data, data_sent_size); 86 if (rc == EFORWARD) {87 goto next;72 if (rc != EFORWARD) { 73 return rc; 88 74 } 89 75 90 return rc;91 92 next:93 handler++;94 76 } 95 77 -
uspace/lib/usbvirt/src/private.h
r5b18137 rb4b534ac 39 39 40 40 int process_control_transfer(usbvirt_device_t *, 41 usbvirt_control_request_handler_t *,42 usb_device_request_setup_packet_t *,41 const usbvirt_control_request_handler_t *, 42 const usb_device_request_setup_packet_t *, 43 43 uint8_t *, size_t *); 44 44 -
uspace/lib/usbvirt/src/stdreq.c
r5b18137 rb4b534ac 51 51 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet, 52 52 uint8_t *data, size_t *act_size, 53 void *actual_data, size_t actual_data_size)53 const void *actual_data, size_t actual_data_size) 54 54 { 55 55 size_t expected_size = setup_packet->length; … … 63 63 *act_size = actual_data_size; 64 64 } 65 } 66 67 /** NOP handler */ 68 int req_nop(usbvirt_device_t *device, 69 const usb_device_request_setup_packet_t *setup_packet, 70 uint8_t *data, size_t *act_size) 71 { 72 return EOK; 65 73 } 66 74 … … 98 106 } 99 107 /* Copy the data. */ 100 usbvirt_device_configuration_t *config = &device->descriptors101 ->configuration[index];108 const usbvirt_device_configuration_t *config = 109 &device->descriptors->configuration[index]; 102 110 uint8_t *all_data = malloc(config->descriptor->total_length); 103 111 if (all_data == NULL) { … … 110 118 size_t i; 111 119 for (i = 0; i < config->extra_count; i++) { 112 usbvirt_device_configuration_extras_t *extra120 const usbvirt_device_configuration_extras_t *extra 113 121 = &config->extra[i]; 114 122 memcpy(ptr, extra->data, extra->length); … … 189 197 } 190 198 199 static int req_get_dev_status(usbvirt_device_t *device, 200 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size) 201 { 202 if (setup_packet->length != 2) 203 return ESTALL; 204 data[0] = (device->self_powered ? 1 : 0) | (device->remote_wakeup ? 2 : 0); 205 data[1] = 0; 206 *act_size = 2; 207 return EOK; 208 } 209 static int req_get_iface_ep_status(usbvirt_device_t *device, 210 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size) 211 { 212 if (setup_packet->length != 2) 213 return ESTALL; 214 data[0] = 0; 215 data[1] = 0; 216 *act_size = 2; 217 return EOK; 218 } 219 191 220 /** Standard request handlers. */ 192 221 usbvirt_control_request_handler_t library_handlers[] = { 193 222 { 194 .req_direction = USB_DIRECTION_OUT, 195 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE, 196 .req_type = USB_REQUEST_TYPE_STANDARD, 197 .request = USB_DEVREQ_SET_ADDRESS, 223 STD_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_SET_ADDRESS), 198 224 .name = "SetAddress", 199 225 .callback = req_set_address 200 226 }, 201 227 { 202 .req_direction = USB_DIRECTION_IN, 203 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE, 204 .req_type = USB_REQUEST_TYPE_STANDARD, 205 .request = USB_DEVREQ_GET_DESCRIPTOR, 206 .name = "GetDescriptor", 228 STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), 229 .name = "GetStdDescriptor", 207 230 .callback = req_get_descriptor 208 231 }, 209 232 { 210 .req_direction = USB_DIRECTION_OUT, 211 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE, 212 .req_type = USB_REQUEST_TYPE_STANDARD, 213 .request = USB_DEVREQ_SET_CONFIGURATION, 233 STD_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_SET_CONFIGURATION), 214 234 .name = "SetConfiguration", 215 235 .callback = req_set_configuration 216 236 }, 217 237 { 238 STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_STATUS), 239 .name = "GetDeviceStatus", 240 .callback = req_get_dev_status, 241 }, 242 { 243 STD_REQ_IN(USB_REQUEST_RECIPIENT_INTERFACE, USB_DEVREQ_GET_STATUS), 244 .name = "GetInterfaceStatus", 245 .callback = req_get_iface_ep_status, 246 }, 247 { 248 /* virtual EPs by default cannot be stalled */ 249 STD_REQ_IN(USB_REQUEST_RECIPIENT_ENDPOINT, USB_DEVREQ_GET_STATUS), 250 .name = "GetEndpointStatus", 251 .callback = req_get_iface_ep_status, 252 }, 218 253 { .callback = NULL } 219 254 }; -
uspace/lib/usbvirt/src/transfer.c
r5b18137 rb4b534ac 51 51 */ 52 52 static int usbvirt_control_transfer(usbvirt_device_t *dev, 53 void *setup, size_t setup_size,53 const void *setup, size_t setup_size, 54 54 void *data, size_t data_size, size_t *data_size_sent) 55 55 { … … 60 60 return ESTALL; 61 61 } 62 usb_device_request_setup_packet_t *setup_packet = setup;62 const usb_device_request_setup_packet_t *setup_packet = setup; 63 63 if (data_size != setup_packet->length) { 64 64 return ESTALL; … … 100 100 * @return Error code. 101 101 */ 102 int usbvirt_control_write(usbvirt_device_t *dev, void *setup, size_t setup_size,103 void *data, size_t data_size)102 int usbvirt_control_write(usbvirt_device_t *dev, const void *setup, 103 size_t setup_size, void *data, size_t data_size) 104 104 { 105 105 return usbvirt_control_transfer(dev, setup, setup_size, … … 119 119 * @return Error code. 120 120 */ 121 int usbvirt_control_read(usbvirt_device_t *dev, void *setup, size_t setup_size,121 int usbvirt_control_read(usbvirt_device_t *dev, const void *setup, size_t setup_size, 122 122 void *data, size_t data_size, size_t *data_size_sent) 123 123 { … … 136 136 */ 137 137 int usbvirt_data_out(usbvirt_device_t *dev, usb_transfer_type_t transf_type, 138 usb_endpoint_t endpoint, void *data, size_t data_size)138 usb_endpoint_t endpoint, const void *data, size_t data_size) 139 139 { 140 140 if ((endpoint <= 0) || (endpoint >= USBVIRT_ENDPOINT_MAX)) {
Note:
See TracChangeset
for help on using the changeset viewer.