Changeset b371844 in mainline
- Timestamp:
- 2010-10-10T11:53:05Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b8100da
- Parents:
- bc9a629
- Location:
- uspace/srv/hw/bus/usb/hcd/virtual
- Files:
-
- 3 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/bus/usb/hcd/virtual/Makefile
rbc9a629 rb371844 33 33 34 34 SOURCES = \ 35 conndev.c \ 36 connhost.c \ 35 37 devices.c \ 36 38 hc.c \ -
uspace/srv/hw/bus/usb/hcd/virtual/devices.c
rbc9a629 rb371844 31 31 */ 32 32 /** @file 33 * @brief 33 * @brief Virtual device management (implementation). 34 34 */ 35 35 … … 53 53 LIST_INITIALIZE(devices); 54 54 55 /** Recognise device by id. 56 * 57 * @param id Device id. 58 * @param phone Callback phone. 59 */ 60 virtdev_connection_t *virtdev_recognise(int id, int phone) 61 { 62 virtdev_connection_t * dev = NULL; 63 switch (id) { 64 case USB_VIRTDEV_KEYBOARD_ID: 65 dev = virtdev_add_device( 66 USB_VIRTDEV_KEYBOARD_ADDRESS, phone); 67 break; 68 default: 69 break; 70 } 71 72 /* 73 * We do not want to mess-up the virtdev_add_device() as 74 * the id is needed only before device probing/detection 75 * is implemented. 76 * 77 * However, that does not mean that this will happen soon. 78 */ 79 if (dev) { 80 dev->id = id; 81 } 82 83 return dev; 84 } 85 86 /** Find virtual device by its USB address. 87 * 88 * @retval NULL No virtual device at given address. 89 */ 55 90 virtdev_connection_t *virtdev_find_by_address(usb_address_t address) 56 91 { … … 67 102 } 68 103 104 /** Create virtual device. 105 * 106 * @param address USB address. 107 * @param phone Callback phone. 108 * @return New device. 109 * @retval NULL Out of memory or address already occupied. 110 */ 69 111 virtdev_connection_t *virtdev_add_device(usb_address_t address, int phone) 70 112 { 113 link_t *pos; 114 list_foreach(pos, &devices) { 115 virtdev_connection_t *dev 116 = list_get_instance(pos, virtdev_connection_t, link); 117 if (dev->address == address) { 118 return NULL; 119 } 120 } 121 71 122 virtdev_connection_t *dev = (virtdev_connection_t *) 72 123 malloc(sizeof(virtdev_connection_t)); … … 78 129 } 79 130 80 void virtdev_destroy_device(virtdev_connection_t *dev) 131 /** Destroy virtual device. 132 */ 133 void virtdev_destroy_device(virtdev_connection_t *dev) 81 134 { 82 135 list_remove(&dev->link); -
uspace/srv/hw/bus/usb/hcd/virtual/devices.h
rbc9a629 rb371844 31 31 */ 32 32 /** @file 33 * @brief 33 * @brief Virtual device management. 34 34 */ 35 35 #ifndef VHCD_DEVICES_H_ … … 39 39 #include <usb/hcd.h> 40 40 41 /** Connected virtual device. */ 41 42 typedef struct { 42 43 /** Assigned USB address. */ … … 44 45 /** Phone used when sending data to device. */ 45 46 int phone; 47 /** Device id. */ 48 int id; 46 49 /** Linked-list handle. */ 47 50 link_t link; 48 51 } virtdev_connection_t; 49 52 53 virtdev_connection_t *virtdev_recognise(int, int); 50 54 virtdev_connection_t *virtdev_find_by_address(usb_address_t); 51 55 virtdev_connection_t *virtdev_add_device(usb_address_t, int); -
uspace/srv/hw/bus/usb/hcd/virtual/hc.c
rbc9a629 rb371844 68 68 static link_t transaction_from_device_list; 69 69 70 70 /** Pending transaction details. */ 71 71 typedef struct { 72 /** Linked-list link. */ 72 73 link_t link; 74 /** Device address. */ 73 75 usb_target_t target; 76 /** Direction of the transaction. */ 74 77 usb_direction_t direction; 78 /** Transfer type. */ 75 79 usb_transfer_type_t type; 80 /** Transaction data buffer. */ 76 81 void * buffer; 82 /** Transaction data length. */ 77 83 size_t len; 84 /** Callback after transaction is done. */ 78 85 hc_transaction_done_callback_t callback; 86 /** Argument to the callback. */ 79 87 void * callback_arg; 80 88 } transaction_t; … … 96 104 } 97 105 106 /** Call transaction callback. 107 * Calling this callback informs the backend that transaction was processed. 108 */ 98 109 static void process_transaction_with_outcome(transaction_t * transaction, 99 110 usb_transaction_outcome_t outcome) … … 103 114 usb_str_transaction_outcome(outcome)); 104 115 105 dprintf(" callback %p (%p, %u, %d, %p)", transaction->callback,106 transaction->buffer, transaction->len, outcome,107 transaction->callback_arg);108 109 116 transaction->callback(transaction->buffer, transaction->len, outcome, 110 117 transaction->callback_arg); 111 dprintf("callback processed"); 112 } 113 114 #if 0 115 static void process_transaction(transaction_t * transaction) 116 { 117 static unsigned int seed = 4089; 118 119 unsigned int roulette = pseudo_random(&seed); 120 usb_transaction_outcome_t outcome = USB_OUTCOME_OK; 121 122 PROB_TEST(outcome, USB_OUTCOME_BABBLE, PROB_OUTCOME_BABBLE, roulette); 123 PROB_TEST(outcome, USB_OUTCOME_CRCERROR, PROB_OUTCOME_CRCERROR, roulette); 124 125 process_transaction_with_outcome(transaction, outcome); 126 } 127 #endif 128 118 } 119 120 /** Host controller manager main function. 121 */ 129 122 void hc_manager(void) 130 123 { … … 150 143 virtdev_connection_t *dev = virtdev_find_by_address( 151 144 transaction->target.address); 145 usb_transaction_outcome_t outcome = USB_OUTCOME_OK; 146 152 147 if (dev != NULL) { 153 dprintf("sending data to device at %d.%d (phone %d) \n",148 dprintf("sending data to device at %d.%d (phone %d)", 154 149 dev->address, transaction->target.endpoint, 155 150 dev->phone); … … 173 168 rc = (int)answer_rc; 174 169 } 170 171 if (rc != EOK) { 172 outcome = USB_OUTCOME_BABBLE; 173 } 175 174 } else { 176 process_transaction_with_outcome(transaction, 177 USB_OUTCOME_OK); 175 outcome = USB_OUTCOME_CRCERROR; 178 176 } 179 177 178 process_transaction_with_outcome(transaction, outcome); 179 180 180 free(transaction); 181 181 } 182 182 } 183 183 184 /** Create new transaction 185 */ 184 186 static transaction_t *transaction_create(usb_transfer_type_t type, usb_target_t target, 185 187 usb_direction_t direction, … … 201 203 } 202 204 203 205 /** Add transaction directioned towards the device. 206 */ 204 207 void hc_add_transaction_to_device(usb_transfer_type_t type, usb_target_t target, 205 208 void * buffer, size_t len, … … 211 214 } 212 215 216 /** Add transaction directioned from the device. 217 */ 213 218 void hc_add_transaction_from_device(usb_transfer_type_t type, usb_target_t target, 214 219 void * buffer, size_t len, … … 220 225 } 221 226 227 /** Fill data to existing transaction from device. 228 */ 222 229 int hc_fillin_transaction_from_device(usb_transfer_type_t type, usb_target_t target, 223 230 void * buffer, size_t len) 224 231 { 225 232 dprintf("finding transaction to fill data in..."); 233 int rc; 234 226 235 /* 227 236 * Find correct transaction envelope in the list. 228 237 */ 229 238 if (list_empty(&transaction_from_device_list)) { 230 return ENOENT; 239 rc = ENOENT; 240 goto leave; 231 241 } 232 242 … … 243 253 } 244 254 if (transaction == NULL) { 245 return ENOENT; 255 rc = ENOENT; 256 goto leave; 246 257 } 247 258 … … 253 264 if (transaction->len < len) { 254 265 process_transaction_with_outcome(transaction, USB_OUTCOME_BABBLE); 255 return ENOMEM; 266 rc = ENOMEM; 267 goto leave; 256 268 } 257 269 … … 264 276 process_transaction_with_outcome(transaction, USB_OUTCOME_OK); 265 277 266 dprintf(" ...transaction " TRANSACTION_FORMAT " sent back",278 dprintf(" ...transaction " TRANSACTION_FORMAT " sent back", 267 279 TRANSACTION_PRINTF(*transaction)); 268 280 269 281 270 282 free(transaction); 271 272 return EOK; 283 rc = EOK; 284 285 leave: 286 dprintf(" ...fill-in transaction: %s", str_error(rc)); 287 288 return rc; 273 289 } 274 290 -
uspace/srv/hw/bus/usb/hcd/virtual/hc.h
rbc9a629 rb371844 38 38 #include <usb/hcd.h> 39 39 40 typedef void (*hc_transaction_done_callback_t)(void *, size_t, usb_transaction_outcome_t, void *); 40 /** Callback after transaction is sent to USB. 41 * 42 * @param buffer Transaction data buffer. 43 * @param size Transaction data size. 44 * @param outcome Transaction outcome. 45 * @param arg Custom argument. 46 */ 47 typedef void (*hc_transaction_done_callback_t)(void *buffer, size_t size, 48 usb_transaction_outcome_t outcome, void *arg); 41 49 42 50 void hc_manager(void); -
uspace/srv/hw/bus/usb/hcd/virtual/hcd.c
rbc9a629 rb371844 49 49 #include "hc.h" 50 50 #include "devices.h" 51 #include "conn.h" 51 52 52 static usb_transaction_handle_t g_handle_seed = 1;53 static usb_transaction_handle_t create_transaction_handle(int phone)54 {55 return g_handle_seed++;56 }57 58 typedef struct {59 int phone;60 usb_transaction_handle_t handle;61 } transaction_details_t;62 63 static void out_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)64 {65 dprintf("out_callback(buffer, %u, %d, %p)", len, outcome, arg);66 (void)len;67 transaction_details_t * trans = (transaction_details_t *)arg;68 69 async_msg_2(trans->phone, IPC_M_USB_HCD_DATA_SENT, trans->handle, outcome);70 71 free(trans);72 free(buffer);73 }74 75 static void in_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)76 {77 dprintf("in_callback(buffer, %u, %d, %p)", len, outcome, arg);78 transaction_details_t * trans = (transaction_details_t *)arg;79 80 ipc_call_t answer_data;81 ipcarg_t answer_rc;82 aid_t req;83 int rc;84 85 req = async_send_3(trans->phone,86 IPC_M_USB_HCD_DATA_RECEIVED,87 trans->handle, outcome,88 len,89 &answer_data);90 91 rc = async_data_write_start(trans->phone, buffer, len);92 if (rc != EOK) {93 async_wait_for(req, NULL);94 goto leave;95 }96 97 async_wait_for(req, &answer_rc);98 rc = (int)answer_rc;99 if (rc != EOK) {100 goto leave;101 }102 103 leave:104 free(trans);105 free(buffer);106 }107 108 109 110 static void handle_data_to_function(ipc_callid_t iid, ipc_call_t icall, int callback_phone)111 {112 usb_transfer_type_t transf_type = IPC_GET_ARG3(icall);113 usb_target_t target = {114 .address = IPC_GET_ARG1(icall),115 .endpoint = IPC_GET_ARG2(icall)116 };117 118 dprintf("pretending transfer to function (dev=%d:%d, type=%s)",119 target.address, target.endpoint,120 usb_str_transfer_type(transf_type));121 122 if (callback_phone == -1) {123 ipc_answer_0(iid, ENOENT);124 return;125 }126 127 usb_transaction_handle_t handle128 = create_transaction_handle(callback_phone);129 130 size_t len;131 void * buffer;132 int rc = async_data_write_accept(&buffer, false,133 1, USB_MAX_PAYLOAD_SIZE,134 0, &len);135 136 if (rc != EOK) {137 ipc_answer_0(iid, rc);138 return;139 }140 141 transaction_details_t * trans = malloc(sizeof(transaction_details_t));142 trans->phone = callback_phone;143 trans->handle = handle;144 145 dprintf("adding transaction to HC", NAME);146 hc_add_transaction_to_device(transf_type, target,147 buffer, len,148 out_callback, trans);149 150 ipc_answer_1(iid, EOK, handle);151 dprintf("transfer to function scheduled (handle %d)", handle);152 }153 154 static void handle_data_from_function(ipc_callid_t iid, ipc_call_t icall, int callback_phone)155 {156 usb_transfer_type_t transf_type = IPC_GET_ARG3(icall);157 usb_target_t target = {158 .address = IPC_GET_ARG1(icall),159 .endpoint = IPC_GET_ARG2(icall)160 };161 size_t len = IPC_GET_ARG4(icall);162 163 dprintf("pretending transfer from function (dev=%d:%d, type=%s)",164 target.address, target.endpoint,165 usb_str_transfer_type(transf_type));166 167 if (callback_phone == -1) {168 ipc_answer_0(iid, ENOENT);169 return;170 }171 172 usb_transaction_handle_t handle173 = create_transaction_handle(callback_phone);174 175 void * buffer = malloc(len);176 177 transaction_details_t * trans = malloc(sizeof(transaction_details_t));178 trans->phone = callback_phone;179 trans->handle = handle;180 181 dprintf("adding transaction to HC", NAME);182 hc_add_transaction_from_device(transf_type, target,183 buffer, len,184 in_callback, trans);185 186 ipc_answer_1(iid, EOK, handle);187 dprintf("transfer from function scheduled (handle %d)", handle);188 }189 190 static void handle_data_from_device(ipc_callid_t iid, ipc_call_t icall, virtdev_connection_t *dev)191 {192 usb_endpoint_t endpoint = IPC_GET_ARG1(icall);193 usb_target_t target = {194 .address = dev->address,195 .endpoint = endpoint196 };197 size_t len;198 void * buffer;199 int rc = async_data_write_accept(&buffer, false,200 1, USB_MAX_PAYLOAD_SIZE,201 0, &len);202 203 if (rc != EOK) {204 ipc_answer_0(iid, rc);205 return;206 }207 208 rc = hc_fillin_transaction_from_device(USB_TRANSFER_INTERRUPT, target, buffer, len);209 210 ipc_answer_0(iid, rc);211 }212 213 static virtdev_connection_t *recognise_device(int id, int callback_phone)214 {215 switch (id) {216 case USB_VIRTDEV_KEYBOARD_ID:217 return virtdev_add_device(218 USB_VIRTDEV_KEYBOARD_ADDRESS, callback_phone);219 default:220 return NULL;221 }222 }223 224 static void device_client_connection(int callback_phone, int device_id)225 {226 virtdev_connection_t *dev = recognise_device(device_id, callback_phone);227 if (!dev) {228 if (callback_phone != -1) {229 ipc_hangup(callback_phone);230 }231 return;232 }233 dprintf("device %d connected", device_id);234 while (true) {235 ipc_callid_t callid;236 ipc_call_t call;237 238 callid = async_get_call(&call);239 240 switch (IPC_GET_METHOD(call)) {241 case IPC_M_PHONE_HUNGUP:242 if (callback_phone != -1) {243 ipc_hangup(callback_phone);244 }245 ipc_answer_0(callid, EOK);246 dprintf("hung-up on device %d", device_id);247 virtdev_destroy_device(dev);248 return;249 case IPC_M_CONNECT_TO_ME:250 ipc_answer_0(callid, ELIMIT);251 break;252 case IPC_M_USB_VIRTDEV_DATA_FROM_DEVICE:253 dprintf("data from device %d", device_id);254 handle_data_from_device(callid, call, dev);255 break;256 default:257 ipc_answer_0(callid, EINVAL);258 break;259 }260 }261 }262 53 263 54 static void client_connection(ipc_callid_t iid, ipc_call_t *icall) … … 268 59 printf("%s: new client connected (phone %#x).\n", NAME, phone_hash); 269 60 270 int callback_phone = -1;271 272 61 while (true) { 273 62 ipc_callid_t callid; … … 275 64 276 65 callid = async_get_call(&call); 277 dprintf("%#x calls method %d", phone_hash, IPC_GET_METHOD(call)); 278 switch (IPC_GET_METHOD(call)) { 279 case IPC_M_PHONE_HUNGUP: 280 if (callback_phone != -1) { 281 ipc_hangup(callback_phone); 66 67 /* 68 * We can do nothing until we have the callback phone. 69 * Thus, we will wait for the callback and start processing 70 * after that. 71 */ 72 int method = (int) IPC_GET_METHOD(call); 73 74 if (method == IPC_M_PHONE_HUNGUP) { 75 ipc_answer_0(callid, EOK); 76 return; 77 } 78 79 if (method == IPC_M_CONNECT_TO_ME) { 80 int kind = IPC_GET_ARG1(call); 81 int callback = IPC_GET_ARG5(call); 82 83 /* 84 * Determine whether host connected to us 85 * or a device. 86 */ 87 if (kind == 0) { 88 ipc_answer_0(callid, EOK); 89 connection_handler_host(phone_hash, callback); 90 return; 91 } else if (kind == 1) { 92 int device_id = IPC_GET_ARG2(call); 93 virtdev_connection_t *dev 94 = virtdev_recognise(device_id, callback); 95 if (!dev) { 96 ipc_answer_0(callid, EEXISTS); 97 ipc_hangup(callback); 98 return; 282 99 } 283 100 ipc_answer_0(callid, EOK); 284 printf("%s: hung-up on %#x.\n", NAME, phone_hash); 101 connection_handler_device(phone_hash, dev); 102 virtdev_destroy_device(dev); 285 103 return; 286 287 case IPC_M_CONNECT_TO_ME: 288 if (callback_phone != -1) { 289 ipc_answer_0(callid, ELIMIT); 290 } else { 291 callback_phone = IPC_GET_ARG5(call); 292 ipc_answer_0(callid, EOK); 293 } 294 if (IPC_GET_ARG1(call) == 1) { 295 /* Virtual device was just connected 296 * to us. This is handled elsewhere. 297 */ 298 device_client_connection(callback_phone, 299 IPC_GET_ARG2(call)); 300 return; 301 } 302 break; 303 304 case IPC_M_USB_HCD_SEND_DATA: 305 handle_data_to_function(callid, call, callback_phone); 306 break; 307 308 case IPC_M_USB_HCD_RECEIVE_DATA: 309 handle_data_from_function(callid, call, callback_phone); 310 break; 311 312 case IPC_M_USB_HCD_TRANSACTION_SIZE: 313 ipc_answer_1(callid, EOK, USB_MAX_PAYLOAD_SIZE); 314 break; 315 316 default: 104 } else { 317 105 ipc_answer_0(callid, EINVAL); 318 break; 106 ipc_hangup(callback); 107 return; 108 } 319 109 } 110 111 /* 112 * No other methods could be served now. 113 */ 114 ipc_answer_0(callid, ENOTSUP); 320 115 } 321 116 } -
uspace/srv/hw/bus/usb/hcd/virtual/vhcd.h
rbc9a629 rb371844 41 41 #define DEVMAP_PATH NAMESPACE "/" NAME 42 42 43 /** Debugging printf. 44 * @see printf 45 */ 43 46 static inline void dprintf(const char * format, ...) 44 47 {
Note:
See TracChangeset
for help on using the changeset viewer.