Changeset b371844 in mainline for uspace/srv/hw/bus/usb/hcd/virtual/hcd.c
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note:
See TracChangeset
for help on using the changeset viewer.