Changeset c48f6ab in mainline
- Timestamp:
- 2011-11-30T20:14:37Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1f5c9c96
- Parents:
- fb48a0e (diff), f9776ae5 (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
- Files:
-
- 2 deleted
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/Makefile
rfb48a0e rc48f6ab 42 42 43 43 SOURCES = \ 44 hc_iface.c \45 44 main.c \ 46 45 pci.c -
uspace/drv/bus/usb/ehci/main.c
rfb48a0e rc48f6ab 42 42 #include <usb/ddfiface.h> 43 43 #include <usb/debug.h> 44 #include <usb/host/hcd.h> 44 45 45 46 #include "pci.h" 46 #include "ehci.h" 47 48 #define NAME "ehci" 47 49 48 50 static int ehci_dev_add(ddf_dev_t *device); … … 57 59 }; 58 60 static ddf_dev_ops_t hc_ops = { 59 .interfaces[USBHC_DEV_IFACE] = & ehci_hc_iface,61 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, 60 62 }; 61 63 … … 95 97 return ENOMEM; 96 98 } 99 hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t)); 100 if (ehci_hc == NULL) { 101 usb_log_error("Failed to alloc generic HC driver.\n"); 102 return ENOMEM; 103 } 104 /* High Speed, no bandwidth */ 105 hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL); 97 106 hc_fun->ops = &hc_ops; 98 107 -
uspace/drv/bus/usb/usbmid/explore.c
rfb48a0e rc48f6ab 54 54 * @return Interface @p interface_no is already present in the list. 55 55 */ 56 static bool interface_in_list( list_t *list, int interface_no)56 static bool interface_in_list(const list_t *list, int interface_no) 57 57 { 58 58 list_foreach(*list, l) { -
uspace/drv/bus/usb/usbmid/usbmid.c
rfb48a0e rc48f6ab 45 45 46 46 /** Callback for DDF USB interface. */ 47 static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle, 48 int *iface_no) 47 static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no) 49 48 { 50 49 assert(fun); … … 64 63 .get_hc_handle = usb_iface_get_hc_handle_device_impl, 65 64 .get_my_address = usb_iface_get_my_address_forward_impl, 66 .get_ interface = usb_iface_get_interface_impl,65 .get_my_interface = usb_iface_get_interface_impl, 67 66 }; 68 67 -
uspace/drv/bus/usb/vhc/connhost.c
rfb48a0e rc48f6ab 508 508 .request_address = request_address, 509 509 .bind_address = bind_address, 510 . find_by_address= find_by_address,510 .get_handle = find_by_address, 511 511 .release_address = release_address, 512 512 -
uspace/lib/drv/generic/remote_usb.c
rfb48a0e rc48f6ab 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 39 40 #include "ddf/driver.h" 40 41 42 typedef enum { 43 IPC_M_USB_GET_MY_ADDRESS, 44 IPC_M_USB_GET_MY_INTERFACE, 45 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, 46 } usb_iface_funcs_t; 47 48 /** Tell USB address assigned to device. 49 * @param exch Vaid IPC exchange 50 * @param address Pointer to address storage place. 51 * @return Error code. 52 * 53 * Exch param is an open communication to device implementing usb_iface. 54 */ 55 int usb_get_my_address(async_exch_t *exch, usb_address_t *address) 56 { 57 if (!exch) 58 return EINVAL; 59 sysarg_t addr; 60 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 61 IPC_M_USB_GET_MY_ADDRESS, &addr); 62 63 if (ret == EOK && address != NULL) 64 *address = (usb_address_t) addr; 65 return ret; 66 } 67 /*----------------------------------------------------------------------------*/ 68 /** Tell interface number given device can use. 69 * @param[in] exch IPC communication exchange 70 * @param[in] handle Id of the device 71 * @param[out] usb_iface Assigned USB interface 72 * @return Error code. 73 */ 74 int usb_get_my_interface(async_exch_t *exch, int *usb_iface) 75 { 76 if (!exch) 77 return EINVAL; 78 sysarg_t iface_no; 79 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 80 IPC_M_USB_GET_MY_INTERFACE, &iface_no); 81 if (ret == EOK && usb_iface) 82 *usb_iface = (int)iface_no; 83 return ret; 84 } 85 /*----------------------------------------------------------------------------*/ 86 /** Tell devman handle of device host controller. 87 * @param[in] exch IPC communication exchange 88 * @param[out] hc_handle devman handle of the HC used by the target device. 89 * @return Error code. 90 */ 91 int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle) 92 { 93 if (!exch) 94 return EINVAL; 95 devman_handle_t h; 96 const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 97 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h); 98 if (ret == EOK && hc_handle) 99 *hc_handle = (devman_handle_t)h; 100 return ret; 101 } 102 41 103 42 104 static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 43 static void remote_usb_get_ interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);105 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 44 106 static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 45 //static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);46 107 47 108 /** Remote USB interface operations. */ 48 109 static remote_iface_func_ptr_t remote_usb_iface_ops [] = { 49 110 [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address, 50 [IPC_M_USB_GET_ INTERFACE] = remote_usb_get_interface,111 [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface, 51 112 [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle, 52 113 }; … … 60 121 }; 61 122 62 123 /*----------------------------------------------------------------------------*/ 63 124 void remote_usb_get_my_address(ddf_fun_t *fun, void *iface, 64 125 ipc_callid_t callid, ipc_call_t *call) 65 126 { 66 usb_iface_t *usb_iface = (usb_iface_t *) iface;127 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 67 128 68 129 if (usb_iface->get_my_address == NULL) { … … 72 133 73 134 usb_address_t address; 74 int rc= usb_iface->get_my_address(fun, &address);75 if (r c!= EOK) {76 async_answer_0(callid, r c);135 const int ret = usb_iface->get_my_address(fun, &address); 136 if (ret != EOK) { 137 async_answer_0(callid, ret); 77 138 } else { 78 139 async_answer_1(callid, EOK, address); 79 140 } 80 141 } 81 82 void remote_usb_get_ interface(ddf_fun_t *fun, void *iface,142 /*----------------------------------------------------------------------------*/ 143 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface, 83 144 ipc_callid_t callid, ipc_call_t *call) 84 145 { 85 usb_iface_t *usb_iface = (usb_iface_t *) iface;146 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 86 147 87 if (usb_iface->get_ interface == NULL) {148 if (usb_iface->get_my_interface == NULL) { 88 149 async_answer_0(callid, ENOTSUP); 89 150 return; 90 151 } 91 152 92 devman_handle_t handle = DEV_IPC_GET_ARG1(*call);93 94 153 int iface_no; 95 int rc = usb_iface->get_interface(fun, handle, &iface_no);96 if (r c!= EOK) {97 async_answer_0(callid, r c);154 const int ret = usb_iface->get_my_interface(fun, &iface_no); 155 if (ret != EOK) { 156 async_answer_0(callid, ret); 98 157 } else { 99 158 async_answer_1(callid, EOK, iface_no); 100 159 } 101 160 } 102 161 /*----------------------------------------------------------------------------*/ 103 162 void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface, 104 163 ipc_callid_t callid, ipc_call_t *call) 105 164 { 106 usb_iface_t *usb_iface = (usb_iface_t *) iface;165 const usb_iface_t *usb_iface = (usb_iface_t *) iface; 107 166 108 167 if (usb_iface->get_hc_handle == NULL) { … … 112 171 113 172 devman_handle_t handle; 114 int rc= usb_iface->get_hc_handle(fun, &handle);115 if (r c!= EOK) {116 async_answer_0(callid, r c);173 const int ret = usb_iface->get_hc_handle(fun, &handle); 174 if (ret != EOK) { 175 async_answer_0(callid, ret); 117 176 } 118 177 119 178 async_answer_1(callid, EOK, (sysarg_t) handle); 120 179 } 121 122 123 124 180 /** 125 181 * @} -
uspace/lib/drv/generic/remote_usbhc.c
rfb48a0e rc48f6ab 1 1 /* 2 2 * Copyright (c) 2010-2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 42 43 #define USB_MAX_PAYLOAD_SIZE 1020 43 44 45 /** IPC methods for communication with HC through DDF interface. 46 * 47 * Notes for async methods: 48 * 49 * Methods for sending data to device (OUT transactions) 50 * - e.g. IPC_M_USBHC_INTERRUPT_OUT - 51 * always use the same semantics: 52 * - first, IPC call with given method is made 53 * - argument #1 is target address 54 * - argument #2 is target endpoint 55 * - argument #3 is max packet size of the endpoint 56 * - this call is immediately followed by IPC data write (from caller) 57 * - the initial call (and the whole transaction) is answer after the 58 * transaction is scheduled by the HC and acknowledged by the device 59 * or immediately after error is detected 60 * - the answer carries only the error code 61 * 62 * Methods for retrieving data from device (IN transactions) 63 * - e.g. IPC_M_USBHC_INTERRUPT_IN - 64 * also use the same semantics: 65 * - first, IPC call with given method is made 66 * - argument #1 is target address 67 * - argument #2 is target endpoint 68 * - this call is immediately followed by IPC data read (async version) 69 * - the call is not answered until the device returns some data (or until 70 * error occurs) 71 * 72 * Some special methods (NO-DATA transactions) do not send any data. These 73 * might behave as both OUT or IN transactions because communication parts 74 * where actual buffers are exchanged are omitted. 75 ** 76 * For all these methods, wrap functions exists. Important rule: functions 77 * for IN transactions have (as parameters) buffers where retrieved data 78 * will be stored. These buffers must be already allocated and shall not be 79 * touch until the transaction is completed 80 * (e.g. not before calling usb_wait_for() with appropriate handle). 81 * OUT transactions buffers can be freed immediately after call is dispatched 82 * (i.e. after return from wrapping function). 83 * 84 */ 85 typedef enum { 86 /** Asks for address assignment by host controller. 87 * Answer: 88 * - ELIMIT - host controller run out of address 89 * - EOK - address assigned 90 * Answer arguments: 91 * - assigned address 92 * 93 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS. 94 */ 95 IPC_M_USBHC_REQUEST_ADDRESS, 96 97 /** Bind USB address with devman handle. 98 * Parameters: 99 * - USB address 100 * - devman handle 101 * Answer: 102 * - EOK - address binded 103 * - ENOENT - address is not in use 104 */ 105 IPC_M_USBHC_BIND_ADDRESS, 106 107 /** Get handle binded with given USB address. 108 * Parameters 109 * - USB address 110 * Answer: 111 * - EOK - address binded, first parameter is the devman handle 112 * - ENOENT - address is not in use at the moment 113 */ 114 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, 115 116 /** Release address in use. 117 * Arguments: 118 * - address to be released 119 * Answer: 120 * - ENOENT - address not in use 121 * - EPERM - trying to release default USB address 122 */ 123 IPC_M_USBHC_RELEASE_ADDRESS, 124 125 /** Register endpoint attributes at host controller. 126 * This is used to reserve portion of USB bandwidth. 127 * When speed is invalid, speed of the device is used. 128 * Parameters: 129 * - USB address + endpoint number 130 * - packed as ADDR << 16 + EP 131 * - speed + transfer type + direction 132 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 133 * - maximum packet size + interval (in milliseconds) 134 * - packed as MPS << 16 + INT 135 * Answer: 136 * - EOK - reservation successful 137 * - ELIMIT - not enough bandwidth to satisfy the request 138 */ 139 IPC_M_USBHC_REGISTER_ENDPOINT, 140 141 /** Revert endpoint registration. 142 * Parameters: 143 * - USB address 144 * - endpoint number 145 * - data direction 146 * Answer: 147 * - EOK - endpoint unregistered 148 * - ENOENT - unknown endpoint 149 */ 150 IPC_M_USBHC_UNREGISTER_ENDPOINT, 151 152 /** Get data from device. 153 * See explanation at usb_iface_funcs_t (IN transaction). 154 */ 155 IPC_M_USBHC_READ, 156 157 /** Send data to device. 158 * See explanation at usb_iface_funcs_t (OUT transaction). 159 */ 160 IPC_M_USBHC_WRITE, 161 } usbhc_iface_funcs_t; 162 163 int usbhc_request_address(async_exch_t *exch, usb_address_t *address, 164 bool strict, usb_speed_t speed) 165 { 166 if (!exch || !address) 167 return EINVAL; 168 sysarg_t new_address; 169 const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 170 IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address); 171 if (ret == EOK) 172 *address = (usb_address_t)new_address; 173 return ret; 174 } 175 /*----------------------------------------------------------------------------*/ 176 int usbhc_bind_address(async_exch_t *exch, usb_address_t address, 177 devman_handle_t handle) 178 { 179 if (!exch) 180 return EINVAL; 181 return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 182 IPC_M_USBHC_BIND_ADDRESS, address, handle); 183 } 184 /*----------------------------------------------------------------------------*/ 185 int usbhc_get_handle(async_exch_t *exch, usb_address_t address, 186 devman_handle_t *handle) 187 { 188 if (!exch) 189 return EINVAL; 190 sysarg_t h; 191 const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 192 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h); 193 if (ret == EOK && handle) 194 *handle = (devman_handle_t)h; 195 return ret; 196 } 197 /*----------------------------------------------------------------------------*/ 198 int usbhc_release_address(async_exch_t *exch, usb_address_t address) 199 { 200 if (!exch) 201 return EINVAL; 202 return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 203 IPC_M_USBHC_RELEASE_ADDRESS, address); 204 } 205 /*----------------------------------------------------------------------------*/ 206 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address, 207 usb_endpoint_t endpoint, usb_transfer_type_t type, 208 usb_direction_t direction, size_t mps, unsigned interval) 209 { 210 if (!exch) 211 return EINVAL; 212 const usb_target_t target = 213 {{ .address = address, .endpoint = endpoint }}; 214 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff)) 215 216 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 217 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 218 _PACK2(type, direction), _PACK2(mps, interval)); 219 220 #undef _PACK2 221 } 222 /*----------------------------------------------------------------------------*/ 223 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address, 224 usb_endpoint_t endpoint, usb_direction_t direction) 225 { 226 if (!exch) 227 return EINVAL; 228 return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 229 IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction); 230 } 231 /*----------------------------------------------------------------------------*/ 232 int usbhc_read(async_exch_t *exch, usb_address_t address, 233 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 234 size_t *rec_size) 235 { 236 if (size == 0 && setup == 0) 237 return EOK; 238 239 if (!exch) 240 return EINVAL; 241 const usb_target_t target = 242 {{ .address = address, .endpoint = endpoint }}; 243 244 /* Make call identifying target USB device and type of transfer. */ 245 aid_t opening_request = async_send_4(exch, 246 DEV_IFACE_ID(USBHC_DEV_IFACE), 247 IPC_M_USBHC_READ, target.packed, 248 (setup & UINT32_MAX), (setup >> 32), NULL); 249 250 if (opening_request == 0) { 251 return ENOMEM; 252 } 253 254 /* Retrieve the data. */ 255 ipc_call_t data_request_call; 256 aid_t data_request = 257 async_data_read(exch, data, size, &data_request_call); 258 259 if (data_request == 0) { 260 // FIXME: How to let the other side know that we want to abort? 261 async_wait_for(opening_request, NULL); 262 return ENOMEM; 263 } 264 265 /* Wait for the answer. */ 266 sysarg_t data_request_rc; 267 sysarg_t opening_request_rc; 268 async_wait_for(data_request, &data_request_rc); 269 async_wait_for(opening_request, &opening_request_rc); 270 271 if (data_request_rc != EOK) { 272 /* Prefer the return code of the opening request. */ 273 if (opening_request_rc != EOK) { 274 return (int) opening_request_rc; 275 } else { 276 return (int) data_request_rc; 277 } 278 } 279 if (opening_request_rc != EOK) { 280 return (int) opening_request_rc; 281 } 282 283 *rec_size = IPC_GET_ARG2(data_request_call); 284 return EOK; 285 } 286 /*----------------------------------------------------------------------------*/ 287 int usbhc_write(async_exch_t *exch, usb_address_t address, 288 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 289 { 290 if (size == 0 && setup == 0) 291 return EOK; 292 293 if (!exch) 294 return EINVAL; 295 const usb_target_t target = 296 {{ .address = address, .endpoint = endpoint }}; 297 298 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 299 IPC_M_USBHC_WRITE, target.packed, size, 300 (setup & UINT32_MAX), (setup >> 32), NULL); 301 302 if (opening_request == 0) { 303 return ENOMEM; 304 } 305 306 /* Send the data if any. */ 307 if (size > 0) { 308 const int ret = async_data_write_start(exch, data, size); 309 if (ret != EOK) { 310 async_wait_for(opening_request, NULL); 311 return ret; 312 } 313 } 314 315 /* Wait for the answer. */ 316 sysarg_t opening_request_rc; 317 async_wait_for(opening_request, &opening_request_rc); 318 319 return (int) opening_request_rc; 320 } 321 /*----------------------------------------------------------------------------*/ 322 44 323 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 45 324 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 46 static void remote_usbhc_ find_by_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);325 static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 47 326 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 48 327 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 57 336 [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address, 58 337 [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address, 59 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_ find_by_address,338 [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle, 60 339 61 340 [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint, … … 78 357 ipc_callid_t data_caller; 79 358 void *buffer; 80 size_t size;81 359 } async_transaction_t; 82 360 … … 103 381 trans->data_caller = 0; 104 382 trans->buffer = NULL; 105 trans->size = 0;106 383 107 384 return trans; 108 385 } 109 386 /*----------------------------------------------------------------------------*/ 110 387 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 111 388 ipc_callid_t callid, ipc_call_t *call) 112 389 { 113 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;390 const usbhc_iface_t *usb_iface = iface; 114 391 115 392 if (!usb_iface->request_address) { … … 129 406 } 130 407 } 131 408 /*----------------------------------------------------------------------------*/ 132 409 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface, 133 410 ipc_callid_t callid, ipc_call_t *call) 134 411 { 135 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;412 const usbhc_iface_t *usb_iface = iface; 136 413 137 414 if (!usb_iface->bind_address) { … … 140 417 } 141 418 142 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 143 devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 144 145 int rc = usb_iface->bind_address(fun, address, handle); 146 147 async_answer_0(callid, rc); 148 } 149 150 void remote_usbhc_find_by_address(ddf_fun_t *fun, void *iface, 419 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 420 const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call); 421 422 const int ret = usb_iface->bind_address(fun, address, handle); 423 async_answer_0(callid, ret); 424 } 425 /*----------------------------------------------------------------------------*/ 426 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface, 151 427 ipc_callid_t callid, ipc_call_t *call) 152 428 { 153 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;154 155 if (!usb_iface-> find_by_address) {156 async_answer_0(callid, ENOTSUP); 157 return; 158 } 159 160 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);429 const usbhc_iface_t *usb_iface = iface; 430 431 if (!usb_iface->get_handle) { 432 async_answer_0(callid, ENOTSUP); 433 return; 434 } 435 436 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 161 437 devman_handle_t handle; 162 int rc = usb_iface->find_by_address(fun, address, &handle);163 164 if (r c== EOK) {165 async_answer_1(callid, EOK, handle);438 const int ret = usb_iface->get_handle(fun, address, &handle); 439 440 if (ret == EOK) { 441 async_answer_1(callid, ret, handle); 166 442 } else { 167 async_answer_0(callid, r c);168 } 169 } 170 443 async_answer_0(callid, ret); 444 } 445 } 446 /*----------------------------------------------------------------------------*/ 171 447 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface, 172 448 ipc_callid_t callid, ipc_call_t *call) 173 449 { 174 usbhc_iface_t *usb_iface = (usbhc_iface_t *)iface;450 const usbhc_iface_t *usb_iface = iface; 175 451 176 452 if (!usb_iface->release_address) { … … 179 455 } 180 456 181 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 182 183 int rc = usb_iface->release_address(fun, address); 184 185 async_answer_0(callid, rc); 186 } 187 188 457 const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call); 458 459 const int ret = usb_iface->release_address(fun, address); 460 async_answer_0(callid, ret); 461 } 462 /*----------------------------------------------------------------------------*/ 189 463 static void callback_out(ddf_fun_t *fun, 190 464 int outcome, void *arg) 191 465 { 192 async_transaction_t *trans = (async_transaction_t *)arg;466 async_transaction_t *trans = arg; 193 467 194 468 async_answer_0(trans->caller, outcome); … … 196 470 async_transaction_destroy(trans); 197 471 } 198 472 /*----------------------------------------------------------------------------*/ 199 473 static void callback_in(ddf_fun_t *fun, 200 474 int outcome, size_t actual_size, void *arg) … … 211 485 } 212 486 213 trans->size = actual_size;214 215 487 if (trans->data_caller) { 216 488 async_data_read_finalize(trans->data_caller, … … 222 494 async_transaction_destroy(trans); 223 495 } 224 496 /*----------------------------------------------------------------------------*/ 225 497 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface, 226 498 ipc_callid_t callid, ipc_call_t *call) … … 300 572 } 301 573 302 if (!async_data_read_receive(&trans->data_caller, &trans->size)) { 574 size_t size = 0; 575 if (!async_data_read_receive(&trans->data_caller, &size)) { 303 576 async_answer_0(callid, EPARTY); 304 577 return; 305 578 } 306 579 307 trans->buffer = malloc( trans->size);580 trans->buffer = malloc(size); 308 581 if (trans->buffer == NULL) { 309 582 async_answer_0(trans->data_caller, ENOMEM); … … 313 586 314 587 const int rc = hc_iface->read( 315 fun, target, setup, trans->buffer, trans->size, callback_in, trans);588 fun, target, setup, trans->buffer, size, callback_in, trans); 316 589 317 590 if (rc != EOK) { … … 321 594 } 322 595 } 323 596 /*----------------------------------------------------------------------------*/ 324 597 void remote_usbhc_write( 325 598 ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call) … … 348 621 } 349 622 623 size_t size = 0; 350 624 if (data_buffer_len > 0) { 351 int rc = async_data_write_accept(&trans->buffer, false,625 const int rc = async_data_write_accept(&trans->buffer, false, 352 626 1, USB_MAX_PAYLOAD_SIZE, 353 0, & trans->size);627 0, &size); 354 628 355 629 if (rc != EOK) { … … 360 634 } 361 635 362 int rc = hc_iface->write(363 fun, target, setup, trans->buffer, trans->size, callback_out, trans);636 const int rc = hc_iface->write( 637 fun, target, setup, trans->buffer, size, callback_out, trans); 364 638 365 639 if (rc != EOK) { … … 368 642 } 369 643 } 370 371 372 644 /** 373 645 * @} -
uspace/lib/drv/include/usb_iface.h
rfb48a0e rc48f6ab 39 39 40 40 #include "ddf/driver.h" 41 #include <async.h> 41 42 #include <usb/usb.h> 42 typedef enum {43 /** Tell USB address assigned to device.44 * Parameters:45 * - devman handle id46 * Answer:47 * - EINVAL - unknown handle or handle not managed by this driver48 * - ENOTSUP - operation not supported (shall not happen)49 * - arbitrary error code if returned by remote implementation50 * - EOK - handle found, first parameter contains the USB address51 *52 * The handle must be the one used for binding USB address with53 * it (IPC_M_USBHC_BIND_ADDRESS), otherwise the host controller54 * (that this request would eventually reach) would not be able55 * to find it.56 * The problem is that this handle is actually assigned to the57 * function inside driver of the parent device (usually hub driver).58 * To bypass this problem, the initial caller specify handle as59 * zero and the first parent assigns the actual value.60 * See usb_iface_get_address_hub_child_impl() implementation61 * that could be assigned to device ops of a child device of in a62 * hub driver.63 * For example, the USB multi interface device driver (MID)64 * passes this initial zero without any modification because the65 * handle must be resolved by its parent.66 */67 IPC_M_USB_GET_MY_ADDRESS,68 43 69 /** Tell interface number given device can use. 70 * Parameters 71 * - devman handle id of the device 72 * Answer: 73 * - ENOTSUP - operation not supported (can also mean any interface) 74 * - EOK - operation okay, first parameter contains interface number 75 */ 76 IPC_M_USB_GET_INTERFACE, 77 78 /** Tell devman handle of device host controller. 79 * Parameters: 80 * - none 81 * Answer: 82 * - EOK - request processed without errors 83 * - ENOTSUP - this indicates invalid USB driver 84 * Parameters of the answer: 85 * - devman handle of HC caller is physically connected to 86 */ 87 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE 88 } usb_iface_funcs_t; 44 int usb_get_my_address(async_exch_t *, usb_address_t *); 45 int usb_get_my_interface(async_exch_t *, int *); 46 int usb_get_hc_handle(async_exch_t *, devman_handle_t *); 89 47 90 48 /** USB device communication interface. */ 91 49 typedef struct { 92 50 int (*get_my_address)(ddf_fun_t *, usb_address_t *); 93 int (*get_ interface)(ddf_fun_t *, devman_handle_t, int *);51 int (*get_my_interface)(ddf_fun_t *, int *); 94 52 int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *); 95 53 } usb_iface_t; 96 97 54 98 55 #endif -
uspace/lib/drv/include/usbhc_iface.h
rfb48a0e rc48f6ab 42 42 #include <bool.h> 43 43 44 45 /** IPC methods for communication with HC through DDF interface. 46 * 47 * Notes for async methods: 48 * 49 * Methods for sending data to device (OUT transactions) 50 * - e.g. IPC_M_USBHC_INTERRUPT_OUT - 51 * always use the same semantics: 52 * - first, IPC call with given method is made 53 * - argument #1 is target address 54 * - argument #2 is target endpoint 55 * - argument #3 is max packet size of the endpoint 56 * - this call is immediately followed by IPC data write (from caller) 57 * - the initial call (and the whole transaction) is answer after the 58 * transaction is scheduled by the HC and acknowledged by the device 59 * or immediately after error is detected 60 * - the answer carries only the error code 61 * 62 * Methods for retrieving data from device (IN transactions) 63 * - e.g. IPC_M_USBHC_INTERRUPT_IN - 64 * also use the same semantics: 65 * - first, IPC call with given method is made 66 * - argument #1 is target address 67 * - argument #2 is target endpoint 68 * - this call is immediately followed by IPC data read (async version) 69 * - the call is not answered until the device returns some data (or until 70 * error occurs) 71 * 72 * Some special methods (NO-DATA transactions) do not send any data. These 73 * might behave as both OUT or IN transactions because communication parts 74 * where actual buffers are exchanged are omitted. 75 ** 76 * For all these methods, wrap functions exists. Important rule: functions 77 * for IN transactions have (as parameters) buffers where retrieved data 78 * will be stored. These buffers must be already allocated and shall not be 79 * touch until the transaction is completed 80 * (e.g. not before calling usb_wait_for() with appropriate handle). 81 * OUT transactions buffers can be freed immediately after call is dispatched 82 * (i.e. after return from wrapping function). 83 * 84 */ 85 typedef enum { 86 /** Asks for address assignment by host controller. 87 * Answer: 88 * - ELIMIT - host controller run out of address 89 * - EOK - address assigned 90 * Answer arguments: 91 * - assigned address 92 * 93 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS. 94 */ 95 IPC_M_USBHC_REQUEST_ADDRESS, 96 97 /** Bind USB address with devman handle. 98 * Parameters: 99 * - USB address 100 * - devman handle 101 * Answer: 102 * - EOK - address binded 103 * - ENOENT - address is not in use 104 */ 105 IPC_M_USBHC_BIND_ADDRESS, 106 107 /** Get handle binded with given USB address. 108 * Parameters 109 * - USB address 110 * Answer: 111 * - EOK - address binded, first parameter is the devman handle 112 * - ENOENT - address is not in use at the moment 113 */ 114 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, 115 116 /** Release address in use. 117 * Arguments: 118 * - address to be released 119 * Answer: 120 * - ENOENT - address not in use 121 * - EPERM - trying to release default USB address 122 */ 123 IPC_M_USBHC_RELEASE_ADDRESS, 124 125 /** Register endpoint attributes at host controller. 126 * This is used to reserve portion of USB bandwidth. 127 * When speed is invalid, speed of the device is used. 128 * Parameters: 129 * - USB address + endpoint number 130 * - packed as ADDR << 16 + EP 131 * - speed + transfer type + direction 132 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 133 * - maximum packet size + interval (in milliseconds) 134 * - packed as MPS << 16 + INT 135 * Answer: 136 * - EOK - reservation successful 137 * - ELIMIT - not enough bandwidth to satisfy the request 138 */ 139 IPC_M_USBHC_REGISTER_ENDPOINT, 140 141 /** Revert endpoint registration. 142 * Parameters: 143 * - USB address 144 * - endpoint number 145 * - data direction 146 * Answer: 147 * - EOK - endpoint unregistered 148 * - ENOENT - unknown endpoint 149 */ 150 IPC_M_USBHC_UNREGISTER_ENDPOINT, 151 152 /** Get data from device. 153 * See explanation at usb_iface_funcs_t (IN transaction). 154 */ 155 IPC_M_USBHC_READ, 156 157 /** Send data to device. 158 * See explanation at usb_iface_funcs_t (OUT transaction). 159 */ 160 IPC_M_USBHC_WRITE, 161 } usbhc_iface_funcs_t; 44 int usbhc_request_address(async_exch_t *, usb_address_t *, bool, usb_speed_t); 45 int usbhc_bind_address(async_exch_t *, usb_address_t, devman_handle_t); 46 int usbhc_get_handle(async_exch_t *, usb_address_t, devman_handle_t *); 47 int usbhc_release_address(async_exch_t *, usb_address_t); 48 int usbhc_register_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t, 49 usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 50 int usbhc_unregister_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t, 51 usb_direction_t); 52 int usbhc_read(async_exch_t *, usb_address_t, usb_endpoint_t, 53 uint64_t, void *, size_t, size_t *); 54 int usbhc_write(async_exch_t *, usb_address_t, usb_endpoint_t, 55 uint64_t, const void *, size_t); 162 56 163 57 /** Callback for outgoing transfer. */ … … 172 66 int (*request_address)(ddf_fun_t *, usb_address_t *, bool, usb_speed_t); 173 67 int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t); 174 int (*find_by_address)(ddf_fun_t *, usb_address_t, devman_handle_t *); 68 int (*get_handle)(ddf_fun_t *, usb_address_t, 69 devman_handle_t *); 175 70 int (*release_address)(ddf_fun_t *, usb_address_t); 176 71 -
uspace/lib/usb/src/ddfiface.c
rfb48a0e rc48f6ab 36 36 #include <devman.h> 37 37 #include <async.h> 38 #include <usb_iface.h> 38 39 #include <usb/ddfiface.h> 39 40 #include <usb/hc.h> … … 104 105 105 106 async_exch_t *exch = async_exchange_begin(parent_sess); 107 if (!exch) { 108 async_hangup(parent_sess); 109 return ENOMEM; 110 } 106 111 107 sysarg_t addr; 108 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 109 IPC_M_USB_GET_MY_ADDRESS, &addr); 112 const int ret = usb_get_my_address(exch, address); 110 113 111 114 async_exchange_end(exch); 112 115 async_hangup(parent_sess); 113 116 114 if (rc != EOK) 115 return rc; 116 117 if (address != NULL) 118 *address = (usb_address_t) addr; 119 120 return EOK; 117 return ret; 121 118 } 122 119 -
uspace/lib/usb/src/hc.c
rfb48a0e rc48f6ab 153 153 if (!usb_hc_connection_is_opened(connection)) 154 154 return ENOENT; 155 155 156 156 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 157 158 sysarg_t tmp; 159 int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 160 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, 161 address, &tmp); 162 157 if (!exch) 158 return ENOMEM; 159 const int ret = usbhc_get_handle(exch, address, handle); 163 160 async_exchange_end(exch); 164 165 if ((rc == EOK) && (handle != NULL)) 166 *handle = tmp; 167 168 return rc; 161 return ret; 169 162 } 170 163 … … 181 174 if (!parent_sess) 182 175 return ENOMEM; 183 176 184 177 async_exch_t *exch = async_exchange_begin(parent_sess); 185 186 sysarg_t address; 187 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 188 IPC_M_USB_GET_MY_ADDRESS, &address); 189 178 if (!exch) { 179 async_hangup(parent_sess); 180 return ENOMEM; 181 } 182 usb_address_t address; 183 const int ret = usb_get_my_address(exch, &address); 184 190 185 async_exchange_end(exch); 191 186 async_hangup(parent_sess); 192 193 if (r c!= EOK)194 return r c;195 196 return (usb_address_t)address;187 188 if (ret != EOK) 189 return ret; 190 191 return address; 197 192 } 198 193 … … 231 226 if (!parent_sess) 232 227 return ENOMEM; 233 228 234 229 async_exch_t *exch = async_exchange_begin(parent_sess); 235 236 devman_handle_t h; 237 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 238 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h); 239 230 if (!exch) { 231 async_hangup(parent_sess); 232 return ENOMEM; 233 } 234 const int ret = usb_get_hc_handle(exch, hc_handle); 235 240 236 async_exchange_end(exch); 241 237 async_hangup(parent_sess); 242 243 if (rc != EOK) 244 return rc; 245 246 if (hc_handle != NULL) 247 *hc_handle = h; 248 249 return EOK; 238 239 return ret; 250 240 } 251 241 -
uspace/lib/usbdev/include/usb/dev/pipes.h
rfb48a0e rc48f6ab 179 179 180 180 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); 181 int usb_pipe_write(usb_pipe_t *, void *, size_t);181 int usb_pipe_write(usb_pipe_t *, const void *, size_t); 182 182 183 183 int usb_pipe_control_read(usb_pipe_t *, const void *, size_t, -
uspace/lib/usbdev/include/usb/dev/request.h
rfb48a0e rc48f6ab 82 82 */ 83 83 uint8_t request_type; 84 #define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7) 85 84 86 /** Request identification. */ 85 87 uint8_t request; -
uspace/lib/usbdev/src/altiface.c
rfb48a0e rc48f6ab 65 65 size_t alternate_count = 0; 66 66 67 const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,68 &dp_data, config_descr);67 const void *iface_ptr = 68 usb_dp_get_nested_descriptor(&dp_parser, &dp_data, config_descr); 69 69 while (iface_ptr != NULL) { 70 usb_standard_interface_descriptor_t *iface 71 = (usb_standard_interface_descriptor_t *) iface_ptr; 72 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) { 73 if (iface->interface_number == interface_no) { 74 alternate_count++; 75 } 70 const usb_standard_interface_descriptor_t *iface = iface_ptr; 71 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE 72 && iface->interface_number == interface_no) { 73 ++alternate_count; 76 74 } 77 75 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, … … 82 80 } 83 81 84 /** Create alternate interface representation structure.82 /** Initialize alternate interface representation structure. 85 83 * 84 * @param[in] alternates Pointer to allocated structure. 86 85 * @param[in] config_descr Configuration descriptor. 87 86 * @param[in] config_descr_size Size of configuration descriptor. 88 87 * @param[in] interface_number Interface number. 89 * @param[out] alternates_ptr Where to store pointer to allocated structure.90 88 * @return Error code. 91 89 */ … … 101 99 alternates->current = 0; 102 100 101 /* No interfaces. */ 103 102 if (interface_number < 0) { 104 103 return EOK; … … 107 106 alternates->alternative_count 108 107 = usb_interface_count_alternates(config_descr, config_descr_size, 109 interface_number);108 interface_number); 110 109 111 110 if (alternates->alternative_count == 0) { … … 128 127 }; 129 128 130 usb_alternate_interface_descriptors_t * cur_alt_iface129 usb_alternate_interface_descriptors_t *iterator 131 130 = &alternates->alternatives[0]; 132 131 133 const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 134 &dp_data, dp_data.data); 135 while (iface_ptr != NULL) { 136 usb_standard_interface_descriptor_t *iface 137 = (usb_standard_interface_descriptor_t *) iface_ptr; 132 const usb_alternate_interface_descriptors_t *end 133 = &alternates->alternatives[alternates->alternative_count]; 134 135 const void *iface_ptr = 136 usb_dp_get_nested_descriptor(&dp_parser, &dp_data, dp_data.data); 137 138 while (iface_ptr != NULL && iterator < end) { 139 const usb_standard_interface_descriptor_t *iface = iface_ptr; 140 138 141 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) 139 142 || (iface->interface_number != interface_number)) { 143 /* This is not a valid alternate interface descriptor 144 * for interface with number == interface_number. */ 140 145 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 141 146 &dp_data, dp_data.data, iface_ptr); … … 143 148 } 144 149 145 cur_alt_iface->interface = iface;146 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);150 iterator->interface = iface; 151 iterator->nested_descriptors = iface_ptr + sizeof(*iface); 147 152 148 153 /* Find next interface to count size of nested descriptors. */ 149 154 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 150 155 dp_data.data, iface_ptr); 151 if (iface_ptr == NULL) {152 const uint8_t *next = dp_data.data + dp_data.size;153 cur_alt_iface->nested_descriptors_size154 = next - cur_alt_iface->nested_descriptors;155 } else {156 cur_alt_iface->nested_descriptors_size157 = iface_ptr - cur_alt_iface->nested_descriptors;158 }159 156 160 cur_alt_iface++; 157 const uint8_t *next = (iface_ptr == NULL) ? 158 dp_data.data + dp_data.size : iface_ptr; 159 160 iterator->nested_descriptors_size 161 = next - iterator->nested_descriptors; 162 163 ++iterator; 161 164 } 162 165 -
uspace/lib/usbdev/src/devpoll.c
rfb48a0e rc48f6ab 46 46 /** Data needed for polling. */ 47 47 typedef struct { 48 int debug; 49 size_t max_failures; 50 useconds_t delay; 51 bool auto_clear_halt; 52 bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *); 53 void (*on_polling_end)(usb_device_t *, bool, void *); 54 bool (*on_error)(usb_device_t *, int, void *); 48 usb_device_auto_polling_t auto_polling; 55 49 56 50 usb_device_t *dev; … … 69 63 static int polling_fibril(void *arg) 70 64 { 71 polling_data_t *polling_data = (polling_data_t *) arg; 72 assert(polling_data); 65 assert(arg); 66 const polling_data_t *data = arg; 67 /* Helper to reduce typing. */ 68 const usb_device_auto_polling_t *params = &data->auto_polling; 73 69 74 70 usb_pipe_t *pipe 75 = & polling_data->dev->pipes[polling_data->pipe_index].pipe;76 77 if (p olling_data->debug > 0) {78 usb_endpoint_mapping_t *mapping79 = & polling_data->dev->pipes[polling_data->pipe_index];71 = &data->dev->pipes[data->pipe_index].pipe; 72 73 if (params->debug > 0) { 74 const usb_endpoint_mapping_t *mapping 75 = &data->dev->pipes[data->pipe_index]; 80 76 usb_log_debug("Poll%p: started polling of `%s' - " \ 81 77 "interface %d (%s,%d,%d), %zuB/%zu.\n", 82 polling_data, 83 polling_data->dev->ddf_dev->name, 78 data, data->dev->ddf_dev->name, 84 79 (int) mapping->interface->interface_number, 85 80 usb_str_class(mapping->interface->interface_class), 86 81 (int) mapping->interface->interface_subclass, 87 82 (int) mapping->interface->interface_protocol, 88 polling_data->request_size, pipe->max_packet_size); 89 } 90 83 data->request_size, pipe->max_packet_size); 84 } 85 86 usb_pipe_start_long_transfer(pipe); 91 87 size_t failed_attempts = 0; 92 while (failed_attempts <= polling_data->max_failures) { 93 int rc; 94 88 while (failed_attempts <= params->max_failures) { 95 89 size_t actual_size; 96 rc = usb_pipe_read(pipe, polling_data->buffer,97 polling_data->request_size, &actual_size);98 99 if (p olling_data->debug > 1) {90 const int rc = usb_pipe_read(pipe, data->buffer, 91 data->request_size, &actual_size); 92 93 if (params->debug > 1) { 100 94 if (rc == EOK) { 101 95 usb_log_debug( 102 96 "Poll%p: received: '%s' (%zuB).\n", 103 polling_data,104 usb_debug_str_buffer( polling_data->buffer,97 data, 98 usb_debug_str_buffer(data->buffer, 105 99 actual_size, 16), 106 100 actual_size); … … 108 102 usb_log_debug( 109 103 "Poll%p: polling failed: %s.\n", 110 polling_data, str_error(rc));104 data, str_error(rc)); 111 105 } 112 106 } 113 107 114 108 /* If the pipe stalled, we can try to reset the stall. */ 115 if ((rc == ESTALL) && (p olling_data->auto_clear_halt)) {109 if ((rc == ESTALL) && (params->auto_clear_halt)) { 116 110 /* 117 111 * We ignore error here as this is usually a futile … … 119 113 */ 120 114 usb_request_clear_endpoint_halt( 121 &polling_data->dev->ctrl_pipe, 122 pipe->endpoint_no); 115 &data->dev->ctrl_pipe, pipe->endpoint_no); 123 116 } 124 117 125 118 if (rc != EOK) { 126 if (polling_data->on_error != NULL) { 127 bool cont = polling_data->on_error( 128 polling_data->dev, rc, 129 polling_data->custom_arg); 130 if (!cont) { 131 failed_attempts 132 = polling_data->max_failures; 133 } 119 ++failed_attempts; 120 const bool cont = (params->on_error == NULL) ? true : 121 params->on_error(data->dev, rc, data->custom_arg); 122 if (!cont) { 123 failed_attempts = params->max_failures; 134 124 } 135 failed_attempts++;136 125 continue; 137 126 } 138 127 139 128 /* We have the data, execute the callback now. */ 140 bool carry_on = polling_data->on_data(polling_data->dev,141 polling_data->buffer, actual_size,142 polling_data->custom_arg);129 assert(params->on_data); 130 const bool carry_on = params->on_data( 131 data->dev, data->buffer, actual_size, data->custom_arg); 143 132 144 133 if (!carry_on) { 134 /* This is user requested abort, erases failures. */ 145 135 failed_attempts = 0; 146 136 break; … … 151 141 152 142 /* Take a rest before next request. */ 153 async_usleep(polling_data->delay); 154 } 155 156 if (polling_data->on_polling_end != NULL) { 157 polling_data->on_polling_end(polling_data->dev, 158 failed_attempts > 0, polling_data->custom_arg); 159 } 160 161 if (polling_data->debug > 0) { 162 if (failed_attempts > 0) { 163 usb_log_error( 164 "Polling of device `%s' terminated: %s.\n", 165 polling_data->dev->ddf_dev->name, 166 "recurring failures"); 143 async_usleep(params->delay); 144 } 145 146 usb_pipe_end_long_transfer(pipe); 147 148 const bool failed = failed_attempts > 0; 149 150 if (params->on_polling_end != NULL) { 151 params->on_polling_end(data->dev, failed, data->custom_arg); 152 } 153 154 if (params->debug > 0) { 155 if (failed) { 156 usb_log_error("Polling of device `%s' terminated: " 157 "recurring failures.\n", data->dev->ddf_dev->name); 167 158 } else { 168 usb_log_debug( 169 "Polling of device `%s' terminated by user.\n", 170 polling_data->dev->ddf_dev->name 171 ); 159 usb_log_debug("Polling of device `%s' terminated: " 160 "driver request.\n", data->dev->ddf_dev->name); 172 161 } 173 162 } 174 163 175 164 /* Free the allocated memory. */ 176 free( polling_data->buffer);177 free( polling_data);165 free(data->buffer); 166 free(data); 178 167 179 168 return EOK; … … 202 191 usb_polling_terminted_callback_t terminated_callback, void *arg) 203 192 { 204 if ((dev == NULL) || (callback == NULL)) {205 return EBADMEM;206 }207 if (request_size == 0) {208 return EINVAL;209 }210 if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)211 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {212 return EINVAL;213 }214 215 193 const usb_device_auto_polling_t auto_polling = { 216 194 .debug = 1, … … 248 226 size_t request_size, void *arg) 249 227 { 250 if ( dev == NULL) {228 if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) { 251 229 return EBADMEM; 252 230 } 253 if (pipe_index >= dev->pipes_count) { 231 232 if (pipe_index >= dev->pipes_count || request_size == 0) { 254 233 return EINVAL; 255 234 } … … 257 236 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) { 258 237 return EINVAL; 259 }260 if ((polling == NULL) || (polling->on_data == NULL)) {261 return EBADMEM;262 238 } 263 239 … … 278 254 polling_data->custom_arg = arg; 279 255 280 polling_data->debug = polling->debug; 281 polling_data->max_failures = polling->max_failures; 282 if (polling->delay >= 0) { 283 polling_data->delay = (useconds_t) polling->delay; 284 } else { 285 polling_data->delay = (useconds_t) dev->pipes[pipe_index] 286 .descriptor->poll_interval; 287 } 288 polling_data->auto_clear_halt = polling->auto_clear_halt; 289 290 polling_data->on_data = polling->on_data; 291 polling_data->on_polling_end = polling->on_polling_end; 292 polling_data->on_error = polling->on_error; 256 /* Copy provided settings. */ 257 polling_data->auto_polling = *polling; 258 259 /* Negative value means use descriptor provided value. */ 260 if (polling->delay < 0) { 261 polling_data->auto_polling.delay = 262 (int) dev->pipes[pipe_index].descriptor->poll_interval; 263 } 293 264 294 265 fid_t fibril = fibril_create(polling_fibril, polling_data); -
uspace/lib/usbdev/src/hub.c
rfb48a0e rc48f6ab 76 76 { 77 77 CHECK_CONNECTION(connection); 78 78 79 79 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 80 81 sysarg_t address; 82 int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address); 84 80 if (!exch) 81 return (usb_address_t)ENOMEM; 82 83 usb_address_t address = preferred; 84 const int ret = usbhc_request_address(exch, &address, strict, speed); 85 85 86 async_exchange_end(exch); 86 87 if (rc != EOK) 88 return (usb_address_t) rc; 89 90 return (usb_address_t) address; 87 return ret == EOK ? address : ret; 91 88 } 92 89 … … 97 94 * @return Error code. 98 95 */ 99 int usb_hc_register_device(usb_hc_connection_t * 96 int usb_hc_register_device(usb_hc_connection_t *connection, 100 97 const usb_hub_attached_device_t *attached_device) 101 98 { 102 99 CHECK_CONNECTION(connection); 103 104 if (attached_device == NULL) 105 return EBADMEM; 106 100 if (attached_device == NULL || attached_device->fun == NULL) 101 return EINVAL; 102 107 103 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 108 int rc = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 109 IPC_M_USBHC_BIND_ADDRESS, 104 if (!exch) 105 return ENOMEM; 106 const int ret = usbhc_bind_address(exch, 110 107 attached_device->address, attached_device->fun->handle); 111 108 async_exchange_end(exch); 112 113 return r c;109 110 return ret; 114 111 } 115 112 … … 124 121 { 125 122 CHECK_CONNECTION(connection); 126 123 127 124 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 128 int rc = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 129 IPC_M_USBHC_RELEASE_ADDRESS, address); 125 if (!exch) 126 return ENOMEM; 127 const int ret = usbhc_release_address(exch, address); 130 128 async_exchange_end(exch); 131 132 return r c;129 130 return ret; 133 131 } 134 132 … … 221 219 * request or requests for descriptors when creating match ids). 222 220 */ 223 int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,224 usb_ speed_t dev_speed,221 int usb_hc_new_device_wrapper(ddf_dev_t *parent, 222 usb_hc_connection_t *connection, usb_speed_t dev_speed, 225 223 int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address, 226 224 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) … … 229 227 return EINVAL; 230 228 231 // FIXME: this is awful, we are accessing directly the structure.232 229 // TODO: Why not use provided connection? 233 usb_hc_connection_t hc_conn = { 234 .hc_handle = connection->hc_handle, 235 .hc_sess = NULL 236 }; 230 usb_hc_connection_t hc_conn; 231 usb_hc_connection_initialize(&hc_conn, connection->hc_handle); 237 232 238 233 int rc; -
uspace/lib/usbdev/src/pipepriv.c
rfb48a0e rc48f6ab 87 87 88 88 if (pipe->refcount == 0) { 89 assert(pipe->hc_sess == NULL); 89 90 /* Need to open the phone by ourselves. */ 90 91 async_sess_t *sess = -
uspace/lib/usbdev/src/pipes.c
rfb48a0e rc48f6ab 54 54 static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev) 55 55 { 56 assert(sess); 56 57 async_exch_t *exch = async_exchange_begin(sess); 57 58 sysarg_t address; 59 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 60 IPC_M_USB_GET_MY_ADDRESS, &address); 61 58 if (!exch) 59 return ENOMEM; 60 61 usb_address_t address; 62 const int ret = usb_get_my_address(exch, &address); 63 62 64 async_exchange_end(exch); 63 64 if (rc != EOK) 65 return rc; 66 67 return (usb_address_t) address; 65 66 return (ret == EOK) ? address : ret; 68 67 } 69 68 … … 71 70 * 72 71 * @param device Device in question. 73 * @return Interface number (negative codemeans any).72 * @return Error code (ENOTSUP means any). 74 73 */ 75 74 int usb_device_get_assigned_interface(const ddf_dev_t *device) … … 80 79 IPC_FLAG_BLOCKING); 81 80 if (!parent_sess) 82 return -1;83 81 return ENOMEM; 82 84 83 async_exch_t *exch = async_exchange_begin(parent_sess); 85 86 sysarg_t iface_no; 87 int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE), 88 IPC_M_USB_GET_INTERFACE, device->handle, &iface_no); 89 90 async_exchange_end(exch); 91 async_hangup(parent_sess); 92 93 if (rc != EOK) 94 return -1; 95 96 return (int) iface_no; 84 if (!exch) { 85 async_hangup(parent_sess); 86 return ENOMEM; 87 } 88 89 int iface_no; 90 const int ret = usb_get_my_interface(exch, &iface_no); 91 92 return ret == EOK ? iface_no : ret; 97 93 } 98 94 -
uspace/lib/usbdev/src/pipesinit.c
rfb48a0e rc48f6ab 54 54 55 55 /** Nesting pairs of standard descriptors. */ 56 static usb_dp_descriptor_nesting_t descriptor_nesting[] = {56 static const usb_dp_descriptor_nesting_t descriptor_nesting[] = { 57 57 NESTING(CONFIGURATION, INTERFACE), 58 58 NESTING(INTERFACE, ENDPOINT), … … 405 405 } 406 406 407 #define TRY_LOOP(attempt_var) \408 for (attempt_var = 0; attempt_var < 3; attempt_var++)409 410 size_t failed_attempts;411 int rc;412 407 413 408 usb_pipe_start_long_transfer(pipe); … … 415 410 uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE]; 416 411 size_t transferred_size; 417 TRY_LOOP(failed_attempts) { 412 int rc; 413 for (size_t attempt_var = 0; attempt_var < 3; ++attempt_var) { 418 414 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD, 419 415 USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE, … … 450 446 { 451 447 assert(pipe); 448 assert(pipe->wire); 452 449 assert(hc_connection); 453 450 454 451 if (!usb_hc_connection_is_opened(hc_connection)) 455 452 return EBADF; 456 457 const usb_target_t target =458 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};459 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))460 461 453 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 462 int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 463 IPC_M_USBHC_REGISTER_ENDPOINT, target.packed, 464 _PACK2(pipe->transfer_type, pipe->direction), 465 _PACK2(pipe->max_packet_size, interval)); 454 if (!exch) 455 return ENOMEM; 456 const int ret = usbhc_register_endpoint(exch, 457 pipe->wire->address, pipe->endpoint_no, pipe->transfer_type, 458 pipe->direction, pipe->max_packet_size, interval); 459 466 460 async_exchange_end(exch); 467 468 #undef _PACK2 469 return rc; 461 return ret; 470 462 } 471 463 … … 482 474 assert(pipe->wire); 483 475 assert(hc_connection); 484 476 485 477 if (!usb_hc_connection_is_opened(hc_connection)) 486 478 return EBADF; 487 479 488 480 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 489 int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 490 IPC_M_USBHC_UNREGISTER_ENDPOINT, 481 if (!exch) 482 return ENOMEM; 483 const int ret = usbhc_unregister_endpoint(exch, 491 484 pipe->wire->address, pipe->endpoint_no, pipe->direction); 492 485 async_exchange_end(exch); 493 494 return r c;486 487 return ret; 495 488 } 496 489 -
uspace/lib/usbdev/src/pipesio.c
rfb48a0e rc48f6ab 62 62 * @return Error code. 63 63 */ 64 static int usb_pipe_read_no_check s(usb_pipe_t *pipe,64 static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup, 65 65 void *buffer, size_t size, size_t *size_transfered) 66 66 { 67 /* Only interrupt and bulk transfers are supported*/67 /* Isochronous transfer are not supported (yet) */ 68 68 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 69 pipe->transfer_type != USB_TRANSFER_BULK) 69 pipe->transfer_type != USB_TRANSFER_BULK && 70 pipe->transfer_type != USB_TRANSFER_CONTROL) 70 71 return ENOTSUP; 71 72 72 const usb_target_t target = 73 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 74 73 int ret = pipe_add_ref(pipe, false); 74 if (ret != EOK) { 75 return ret; 76 } 77 75 78 /* Ensure serialization over the phone. */ 76 79 pipe_start_transaction(pipe); 77 80 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 78 79 /* 80 * Make call identifying target USB device and type of transfer. 81 */ 82 aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_READ, target.packed, NULL); 84 85 if (opening_request == 0) { 86 async_exchange_end(exch); 81 if (!exch) { 87 82 pipe_end_transaction(pipe); 83 pipe_drop_ref(pipe); 88 84 return ENOMEM; 89 85 } 90 91 /* 92 * Retrieve the data. 93 */ 94 ipc_call_t data_request_call; 95 aid_t data_request = async_data_read(exch, buffer, size, 96 &data_request_call); 97 98 /* 99 * Since now on, someone else might access the backing phone 100 * without breaking the transfer IPC protocol. 101 */ 86 87 ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no, 88 setup, buffer, size, size_transfered); 102 89 async_exchange_end(exch); 103 90 pipe_end_transaction(pipe); 104 105 if (data_request == 0) {106 /*107 * FIXME:108 * How to let the other side know that we want to abort?109 */110 async_wait_for(opening_request, NULL);111 return ENOMEM;112 }113 114 /*115 * Wait for the answer.116 */117 sysarg_t data_request_rc;118 sysarg_t opening_request_rc;119 async_wait_for(data_request, &data_request_rc);120 async_wait_for(opening_request, &opening_request_rc);121 122 if (data_request_rc != EOK) {123 /* Prefer the return code of the opening request. */124 if (opening_request_rc != EOK) {125 return (int) opening_request_rc;126 } else {127 return (int) data_request_rc;128 }129 }130 if (opening_request_rc != EOK) {131 return (int) opening_request_rc;132 }133 134 *size_transfered = IPC_GET_ARG2(data_request_call);135 136 return EOK;137 }138 139 140 /** Request a read (in) transfer on an endpoint pipe.141 *142 * @param[in] pipe Pipe used for the transfer.143 * @param[out] buffer Buffer where to store the data.144 * @param[in] size Size of the buffer (in bytes).145 * @param[out] size_transfered Number of bytes that were actually transfered.146 * @return Error code.147 */148 int usb_pipe_read(usb_pipe_t *pipe,149 void *buffer, size_t size, size_t *size_transfered)150 {151 assert(pipe);152 153 if (buffer == NULL) {154 return EINVAL;155 }156 157 if (size == 0) {158 return EINVAL;159 }160 161 if (pipe->direction != USB_DIRECTION_IN) {162 return EBADF;163 }164 165 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {166 return EBADF;167 }168 169 int rc;170 rc = pipe_add_ref(pipe, false);171 if (rc != EOK) {172 return rc;173 }174 175 176 size_t act_size = 0;177 178 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);179 180 91 pipe_drop_ref(pipe); 181 182 if (rc != EOK) { 183 return rc; 184 } 185 186 if (size_transfered != NULL) { 187 *size_transfered = act_size; 188 } 189 190 return EOK; 191 } 192 193 194 92 return ret; 93 } 195 94 196 95 /** Request an out transfer, no checking of input parameters. … … 201 100 * @return Error code. 202 101 */ 203 static int usb_pipe_write_no_check(usb_pipe_t *pipe, 204 void *buffer, size_t size)102 static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup, 103 const void *buffer, size_t size) 205 104 { 206 105 /* Only interrupt and bulk transfers are supported */ 207 106 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 208 pipe->transfer_type != USB_TRANSFER_BULK) 107 pipe->transfer_type != USB_TRANSFER_BULK && 108 pipe->transfer_type != USB_TRANSFER_CONTROL) 209 109 return ENOTSUP; 210 110 211 const usb_target_t target = 212 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }}; 111 int ret = pipe_add_ref(pipe, false); 112 if (ret != EOK) { 113 return ret; 114 } 213 115 214 116 /* Ensure serialization over the phone. */ 215 117 pipe_start_transaction(pipe); 216 118 async_exch_t *exch = async_exchange_begin(pipe->hc_sess); 217 218 /* 219 * Make call identifying target USB device and type of transfer. 220 */ 221 aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE), 222 IPC_M_USBHC_WRITE, target.packed, size, NULL); 223 224 if (opening_request == 0) { 225 async_exchange_end(exch); 119 if (!exch) { 226 120 pipe_end_transaction(pipe); 121 pipe_drop_ref(pipe); 227 122 return ENOMEM; 228 123 } 229 230 /* 231 * Send the data. 232 */ 233 int rc = async_data_write_start(exch, buffer, size); 234 235 /* 236 * Since now on, someone else might access the backing phone 237 * without breaking the transfer IPC protocol. 238 */ 124 ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no, 125 setup, buffer, size); 239 126 async_exchange_end(exch); 240 127 pipe_end_transaction(pipe); 241 242 if (rc != EOK) {243 async_wait_for(opening_request, NULL);244 return rc;245 }246 247 /*248 * Wait for the answer.249 */250 sysarg_t opening_request_rc;251 async_wait_for(opening_request, &opening_request_rc);252 253 return (int) opening_request_rc;254 }255 256 /** Request a write (out) transfer on an endpoint pipe.257 *258 * @param[in] pipe Pipe used for the transfer.259 * @param[in] buffer Buffer with data to transfer.260 * @param[in] size Size of the buffer (in bytes).261 * @return Error code.262 */263 int usb_pipe_write(usb_pipe_t *pipe,264 void *buffer, size_t size)265 {266 assert(pipe);267 268 if (buffer == NULL) {269 return EINVAL;270 }271 272 if (size == 0) {273 return EINVAL;274 }275 276 if (pipe->direction != USB_DIRECTION_OUT) {277 return EBADF;278 }279 280 if (pipe->transfer_type == USB_TRANSFER_CONTROL) {281 return EBADF;282 }283 284 int rc;285 286 rc = pipe_add_ref(pipe, false);287 if (rc != EOK) {288 return rc;289 }290 291 rc = usb_pipe_write_no_check(pipe, buffer, size);292 293 128 pipe_drop_ref(pipe); 294 295 return rc; 129 return ret; 296 130 } 297 131 … … 309 143 310 144 311 /* Prevent in definite recursion. */145 /* Prevent infinite recursion. */ 312 146 pipe->auto_reset_halt = false; 313 147 usb_request_clear_endpoint_halt(pipe, 0); … … 315 149 } 316 150 317 318 /** Request a control read transfer, no checking of input parameters. 151 /** Request a control read transfer on an endpoint pipe. 152 * 153 * This function encapsulates all three stages of a control transfer. 319 154 * 320 155 * @param[in] pipe Pipe used for the transfer. … … 327 162 * @return Error code. 328 163 */ 329 static int usb_pipe_control_read_no_check(usb_pipe_t *pipe,330 const void *setup_buffer, size_t setup_buffer_size,331 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)332 {333 /* Ensure serialization over the phone. */334 pipe_start_transaction(pipe);335 336 const usb_target_t target =337 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};338 339 assert(setup_buffer_size == 8);340 uint64_t setup_packet;341 memcpy(&setup_packet, setup_buffer, 8);342 /*343 * Make call identifying target USB device and control transfer type.344 */345 async_exch_t *exch = async_exchange_begin(pipe->hc_sess);346 aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),347 IPC_M_USBHC_READ, target.packed,348 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);349 350 if (opening_request == 0) {351 async_exchange_end(exch);352 return ENOMEM;353 }354 355 /*356 * Retrieve the data.357 */358 ipc_call_t data_request_call;359 aid_t data_request = async_data_read(exch, data_buffer,360 data_buffer_size, &data_request_call);361 362 /*363 * Since now on, someone else might access the backing phone364 * without breaking the transfer IPC protocol.365 */366 async_exchange_end(exch);367 pipe_end_transaction(pipe);368 369 if (data_request == 0) {370 async_wait_for(opening_request, NULL);371 return ENOMEM;372 }373 374 /*375 * Wait for the answer.376 */377 sysarg_t data_request_rc;378 sysarg_t opening_request_rc;379 async_wait_for(data_request, &data_request_rc);380 async_wait_for(opening_request, &opening_request_rc);381 382 if (data_request_rc != EOK) {383 /* Prefer the return code of the opening request. */384 if (opening_request_rc != EOK) {385 return (int) opening_request_rc;386 } else {387 return (int) data_request_rc;388 }389 }390 if (opening_request_rc != EOK) {391 return (int) opening_request_rc;392 }393 394 *data_transfered_size = IPC_GET_ARG2(data_request_call);395 396 return EOK;397 }398 399 /** Request a control read transfer on an endpoint pipe.400 *401 * This function encapsulates all three stages of a control transfer.402 *403 * @param[in] pipe Pipe used for the transfer.404 * @param[in] setup_buffer Buffer with the setup packet.405 * @param[in] setup_buffer_size Size of the setup packet (in bytes).406 * @param[out] data_buffer Buffer for incoming data.407 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).408 * @param[out] data_transfered_size Number of bytes that were actually409 * transfered during the DATA stage.410 * @return Error code.411 */412 164 int usb_pipe_control_read(usb_pipe_t *pipe, 413 165 const void *setup_buffer, size_t setup_buffer_size, … … 416 168 assert(pipe); 417 169 418 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {170 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 419 171 return EINVAL; 420 172 } … … 429 181 } 430 182 431 int rc; 432 433 rc = pipe_add_ref(pipe, false); 434 if (rc != EOK) { 435 return rc; 436 } 183 uint64_t setup_packet; 184 memcpy(&setup_packet, setup_buffer, 8); 437 185 438 186 size_t act_size = 0; 439 rc = usb_pipe_control_read_no_check(pipe, 440 setup_buffer, setup_buffer_size, 187 const int rc = usb_pipe_read_no_check(pipe, setup_packet, 441 188 data_buffer, data_buffer_size, &act_size); 442 189 … … 445 192 } 446 193 447 pipe_drop_ref(pipe); 448 449 if (rc != EOK) { 450 return rc; 451 } 452 453 if (data_transfered_size != NULL) { 194 if (rc == EOK && data_transfered_size != NULL) { 454 195 *data_transfered_size = act_size; 455 196 } 456 197 457 return EOK; 458 } 459 460 461 /** Request a control write transfer, no checking of input parameters. 198 return rc; 199 } 200 201 /** Request a control write transfer on an endpoint pipe. 202 * 203 * This function encapsulates all three stages of a control transfer. 462 204 * 463 205 * @param[in] pipe Pipe used for the transfer. … … 468 210 * @return Error code. 469 211 */ 470 static int usb_pipe_control_write_no_check(usb_pipe_t *pipe,471 const void *setup_buffer, size_t setup_buffer_size,472 const void *data_buffer, size_t data_buffer_size)473 {474 /* Ensure serialization over the phone. */475 pipe_start_transaction(pipe);476 477 const usb_target_t target =478 {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};479 assert(setup_buffer_size == 8);480 uint64_t setup_packet;481 memcpy(&setup_packet, setup_buffer, 8);482 483 /*484 * Make call identifying target USB device and control transfer type.485 */486 async_exch_t *exch = async_exchange_begin(pipe->hc_sess);487 aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),488 IPC_M_USBHC_WRITE, target.packed, data_buffer_size,489 (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);490 491 if (opening_request == 0) {492 async_exchange_end(exch);493 pipe_end_transaction(pipe);494 return ENOMEM;495 }496 497 /*498 * Send the data (if any).499 */500 if (data_buffer_size > 0) {501 int rc = async_data_write_start(exch, data_buffer, data_buffer_size);502 503 /* All data sent, pipe can be released. */504 async_exchange_end(exch);505 pipe_end_transaction(pipe);506 507 if (rc != EOK) {508 async_wait_for(opening_request, NULL);509 return rc;510 }511 } else {512 /* No data to send, we can release the pipe for others. */513 async_exchange_end(exch);514 pipe_end_transaction(pipe);515 }516 517 /*518 * Wait for the answer.519 */520 sysarg_t opening_request_rc;521 async_wait_for(opening_request, &opening_request_rc);522 523 return (int) opening_request_rc;524 }525 526 /** Request a control write transfer on an endpoint pipe.527 *528 * This function encapsulates all three stages of a control transfer.529 *530 * @param[in] pipe Pipe used for the transfer.531 * @param[in] setup_buffer Buffer with the setup packet.532 * @param[in] setup_buffer_size Size of the setup packet (in bytes).533 * @param[in] data_buffer Buffer with data to be sent.534 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).535 * @return Error code.536 */537 212 int usb_pipe_control_write(usb_pipe_t *pipe, 538 213 const void *setup_buffer, size_t setup_buffer_size, … … 541 216 assert(pipe); 542 217 543 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {218 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 544 219 return EINVAL; 545 220 } … … 558 233 } 559 234 560 int rc; 561 562 rc = pipe_add_ref(pipe, false); 563 if (rc != EOK) { 564 return rc; 565 } 566 567 rc = usb_pipe_control_write_no_check(pipe, 568 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 235 uint64_t setup_packet; 236 memcpy(&setup_packet, setup_buffer, 8); 237 238 const int rc = usb_pipe_write_no_check(pipe, setup_packet, 239 data_buffer, data_buffer_size); 569 240 570 241 if (rc == ESTALL) { … … 572 243 } 573 244 574 pipe_drop_ref(pipe);575 576 245 return rc; 577 246 } 578 247 248 /** Request a read (in) transfer on an endpoint pipe. 249 * 250 * @param[in] pipe Pipe used for the transfer. 251 * @param[out] buffer Buffer where to store the data. 252 * @param[in] size Size of the buffer (in bytes). 253 * @param[out] size_transfered Number of bytes that were actually transfered. 254 * @return Error code. 255 */ 256 int usb_pipe_read(usb_pipe_t *pipe, 257 void *buffer, size_t size, size_t *size_transfered) 258 { 259 assert(pipe); 260 261 if (buffer == NULL) { 262 return EINVAL; 263 } 264 265 if (size == 0) { 266 return EINVAL; 267 } 268 269 if (pipe->direction != USB_DIRECTION_IN) { 270 return EBADF; 271 } 272 273 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 274 return EBADF; 275 } 276 277 size_t act_size = 0; 278 const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size); 279 280 281 if (rc == EOK && size_transfered != NULL) { 282 *size_transfered = act_size; 283 } 284 285 return rc; 286 } 287 288 /** Request a write (out) transfer on an endpoint pipe. 289 * 290 * @param[in] pipe Pipe used for the transfer. 291 * @param[in] buffer Buffer with data to transfer. 292 * @param[in] size Size of the buffer (in bytes). 293 * @return Error code. 294 */ 295 int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size) 296 { 297 assert(pipe); 298 299 if (buffer == NULL || size == 0) { 300 return EINVAL; 301 } 302 303 if (pipe->direction != USB_DIRECTION_OUT) { 304 return EBADF; 305 } 306 307 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 308 return EBADF; 309 } 310 311 return usb_pipe_write_no_check(pipe, 0, buffer, size); 312 } 579 313 580 314 /** -
uspace/lib/usbdev/src/request.c
rfb48a0e rc48f6ab 143 143 */ 144 144 145 usb_device_request_setup_packet_t setup_packet; 146 setup_packet.request_type = 128 | (request_type << 5) | recipient; 147 setup_packet.request = request; 148 setup_packet.value = value; 149 setup_packet.index = index; 150 setup_packet.length = (uint16_t) data_size; 151 152 int rc = usb_pipe_control_read(pipe, 153 &setup_packet, sizeof(setup_packet), 145 const usb_device_request_setup_packet_t setup_packet = { 146 .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST 147 | (request_type << 5) | recipient, 148 .request = request, 149 .value = value, 150 .index = index, 151 .length = (uint16_t) data_size, 152 }; 153 154 return usb_pipe_control_read(pipe, &setup_packet, sizeof(setup_packet), 154 155 data, data_size, actual_data_size); 155 156 return rc;157 156 } 158 157 … … 276 275 } 277 276 278 uint16_t wValue = descriptor_index | (descriptor_type << 8);277 const uint16_t wValue = descriptor_index | (descriptor_type << 8); 279 278 280 279 return usb_control_request_get(pipe, -
uspace/lib/usbhost/include/usb/host/hcd.h
rfb48a0e rc48f6ab 63 63 /*----------------------------------------------------------------------------*/ 64 64 /** Initialize hcd_t structure. 65 * Initializes device and endpoint managers. Sets data nd hook pointer to NULL.65 * Initializes device and endpoint managers. Sets data and hook pointer to NULL. 66 66 * @param hcd hcd_t structure to initialize, non-null. 67 67 * @param bandwidth Available bandwidth, passed to endpoint manager. -
uspace/lib/usbhost/src/iface.c
rfb48a0e rc48f6ab 252 252 .request_address = request_address, 253 253 .bind_address = bind_address, 254 . find_by_address= find_by_address,254 .get_handle = find_by_address, 255 255 .release_address = release_address, 256 256
Note:
See TracChangeset
for help on using the changeset viewer.