Changeset 91db50ac in mainline for uspace/lib/usb/usbdrv.c
- Timestamp:
- 2010-11-19T21:50:46Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7034be15
- Parents:
- 63b4f90
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/usbdrv.c
r63b4f90 r91db50ac 34 34 */ 35 35 #include "usbdrv.h" 36 #include <usb_iface.h> 36 37 #include <errno.h> 37 38 39 /** Information about pending transaction on HC. */ 40 typedef struct { 41 /** Phone to host controller driver. */ 42 int phone; 43 /** Data buffer. */ 44 void *buffer; 45 /** Buffer size. */ 46 size_t size; 47 /** Storage for actual number of bytes transferred. */ 48 size_t *size_transferred; 49 /** Initial call replay data. */ 50 ipc_call_t reply; 51 /** Initial call identifier. */ 52 aid_t request; 53 } transfer_info_t; 54 38 55 /** Connect to host controller the device is physically attached to. 39 * This function sets the phone_parent property in the device_t struct.40 56 * 41 57 * @param handle Device handle. 42 58 * @param flags Connection flags (blocking connection). 43 * @return Error code.59 * @return Phone to corresponding HC or error code. 44 60 */ 45 61 int usb_drv_hc_connect(device_t *dev, unsigned int flags) … … 51 67 } 52 68 69 /** Send data to HCD. 70 * 71 * @param phone Phone to HC. 72 * @param method Method used for calling. 73 * @param endpoint Device endpoint. 74 * @param buffer Data buffer (NULL to skip data transfer phase). 75 * @param size Buffer size (must be zero when @p buffer is NULL). 76 * @param handle Storage for transaction handle (cannot be NULL). 77 * @return Error status. 78 * @retval EINVAL Invalid parameter. 79 * @retval ENOMEM Not enough memory to complete the operation. 80 */ 81 static int async_send_buffer(int phone, int method, 82 usb_endpoint_t endpoint, 83 void *buffer, size_t size, 84 usb_handle_t *handle) 85 { 86 if (phone < 0) { 87 return EINVAL; 88 } 89 90 if ((buffer == NULL) && (size > 0)) { 91 return EINVAL; 92 } 93 94 if (handle == NULL) { 95 return EINVAL; 96 } 97 98 transfer_info_t *transfer 99 = (transfer_info_t *) malloc(sizeof(transfer_info_t)); 100 if (transfer == NULL) { 101 return ENOMEM; 102 } 103 104 transfer->size_transferred = NULL; 105 transfer->buffer = NULL; 106 transfer->size = 0; 107 transfer->phone = phone; 108 109 int rc; 110 111 transfer->request = async_send_3(phone, 112 DEV_IFACE_ID(USB_DEV_IFACE), 113 method, 114 endpoint, 115 size, 116 &transfer->reply); 117 118 if (size > 0) { 119 rc = async_data_write_start(phone, buffer, size); 120 if (rc != EOK) { 121 async_wait_for(transfer->request, NULL); 122 return rc; 123 } 124 } 125 126 *handle = (usb_handle_t) transfer; 127 128 return EOK; 129 } 130 131 /** Prepare data retrieval. 132 * 133 * @param phone Opened phone to HCD. 134 * @param method Method used for calling. 135 * @param endpoint Device endpoint. 136 * @param buffer Buffer where to store retrieved data 137 * (NULL to skip data transfer phase). 138 * @param size Buffer size (must be zero when @p buffer is NULL). 139 * @param actual_size Storage where actual number of bytes transferred will 140 * be stored. 141 * @param handle Storage for transaction handle (cannot be NULL). 142 * @return Error status. 143 * @retval EINVAL Invalid parameter. 144 * @retval ENOMEM Not enough memory to complete the operation. 145 */ 146 static int async_recv_buffer(int phone, int method, 147 usb_endpoint_t endpoint, 148 void *buffer, size_t size, size_t *actual_size, 149 usb_handle_t *handle) 150 { 151 if (phone < 0) { 152 return EINVAL; 153 } 154 155 if ((buffer == NULL) && (size > 0)) { 156 return EINVAL; 157 } 158 159 if (handle == NULL) { 160 return EINVAL; 161 } 162 163 transfer_info_t *transfer 164 = (transfer_info_t *) malloc(sizeof(transfer_info_t)); 165 if (transfer == NULL) { 166 return ENOMEM; 167 } 168 169 transfer->size_transferred = actual_size; 170 transfer->buffer = buffer; 171 transfer->size = size; 172 transfer->phone = phone; 173 174 transfer->request = async_send_3(phone, 175 DEV_IFACE_ID(USB_DEV_IFACE), 176 method, 177 endpoint, 178 size, 179 &transfer->reply); 180 181 *handle = (usb_handle_t) transfer; 182 183 return EOK; 184 } 185 186 /** Read buffer from HCD. 187 * 188 * @param phone Opened phone to HCD. 189 * @param hash Buffer hash (obtained after completing IN transaction). 190 * @param buffer Buffer where to store data data. 191 * @param size Buffer size. 192 * @param actual_size Storage where actual number of bytes transferred will 193 * be stored. 194 * @return Error status. 195 */ 196 static int read_buffer_in(int phone, ipcarg_t hash, 197 void *buffer, size_t size, size_t *actual_size) 198 { 199 ipc_call_t answer_data; 200 ipcarg_t answer_rc; 201 aid_t req; 202 int rc; 203 204 req = async_send_2(phone, 205 DEV_IFACE_ID(USB_DEV_IFACE), 206 IPC_M_USB_GET_BUFFER, 207 hash, 208 &answer_data); 209 210 rc = async_data_read_start(phone, buffer, size); 211 if (rc != EOK) { 212 async_wait_for(req, NULL); 213 return EINVAL; 214 } 215 216 async_wait_for(req, &answer_rc); 217 rc = (int)answer_rc; 218 219 if (rc != EOK) { 220 return rc; 221 } 222 223 *actual_size = IPC_GET_ARG1(answer_data); 224 225 return EOK; 226 } 227 228 /** Blocks caller until given USB transaction is finished. 229 * After the transaction is finished, the user can access all output data 230 * given to initial call function. 231 * 232 * @param handle Transaction handle. 233 * @return Error status. 234 * @retval EOK No error. 235 * @retval EBADMEM Invalid handle. 236 * @retval ENOENT Data buffer associated with transaction does not exist. 237 */ 238 int usb_drv_async_wait_for(usb_handle_t handle) 239 { 240 if (handle == 0) { 241 return EBADMEM; 242 } 243 244 int rc = EOK; 245 246 transfer_info_t *transfer = (transfer_info_t *) handle; 247 248 ipcarg_t answer_rc; 249 async_wait_for(transfer->request, &answer_rc); 250 251 if (answer_rc != EOK) { 252 rc = (int) answer_rc; 253 goto leave; 254 } 255 256 /* 257 * If the buffer is not NULL, we must accept some data. 258 */ 259 if ((transfer->buffer != NULL) && (transfer->size > 0)) { 260 /* 261 * The buffer hash identifies the data on the server 262 * side. 263 * We will use it when actually reading-in the data. 264 */ 265 ipcarg_t buffer_hash = IPC_GET_ARG1(transfer->reply); 266 if (buffer_hash == 0) { 267 rc = ENOENT; 268 goto leave; 269 } 270 271 size_t actual_size; 272 rc = read_buffer_in(transfer->phone, buffer_hash, 273 transfer->buffer, transfer->size, &actual_size); 274 275 if (rc != EOK) { 276 goto leave; 277 } 278 279 if (transfer->size_transferred) { 280 *(transfer->size_transferred) = actual_size; 281 } 282 } 283 284 leave: 285 free(transfer); 286 287 return rc; 288 } 289 290 /** Send interrupt data to device. */ 291 int usb_drv_async_interrupt_out(int phone, usb_endpoint_t endpoint, 292 void *buffer, size_t size, 293 usb_handle_t *handle) 294 { 295 return async_send_buffer(phone, 296 IPC_M_USB_INTERRUPT_OUT, 297 endpoint, 298 buffer, size, 299 handle); 300 } 301 302 /** Request interrupt data from device. */ 303 int usb_drv_async_interrupt_in(int phone, usb_endpoint_t endpoint, 304 void *buffer, size_t size, size_t *actual_size, 305 usb_handle_t *handle) 306 { 307 return async_recv_buffer(phone, 308 IPC_M_USB_INTERRUPT_IN, 309 endpoint, 310 buffer, size, actual_size, 311 handle); 312 } 53 313 54 314 /**
Note:
See TracChangeset
for help on using the changeset viewer.