static void *novacom_usb_tx_thread(void *arg) { novacom_usb_handle_t *handle = (novacom_usb_handle_t *)arg; int rc; struct novacom_tx_packet packet; char *buf; buf = platform_calloc(MAX_MTU); platform_assert(buf != NULL); LTRACEF("start::wait for startup event: %p\n", handle); platform_event_wait(&handle->tx_startup_event); //why waiting rx for starting ??? handle->tx_startup_wait = 0; //change status to started LTRACEF("start::startup event received, continue: %p\n", handle); handle->tx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); while (!novacom_shutdown && !handle->shutdown) { // see if we have something to send packet.len = novacom_usbll_get_mtu(handle->usbll_handle); packet.buf = buf; if (novacom_usbll_prepare_tx_packet(handle->usbll_handle, &packet, 100) != TX_NO_PACKET) { // write a block back #if FAULTY_TX if (rand() < (RAND_MAX / 10)) { TRACEF("dropped tx packet\n"); } else { #endif rc = novacom_usb_write(handle, packet.buf, packet.len); if (rc < 0) { platform_time_t st; platform_time_t et; int time_used = 0; unsigned int count = 0; TRACEL(LOG_ALWAYS, "usbll(%08x) error writing packet, result(%d), errno %d\n", novacom_usbll_getuid(handle->usbll_handle), rc, errno); platform_get_time(&st); while (rc < 0 && !handle->shutdown) { //shutdown asap platform_get_time(&et); if (platform_delta_time_msecs(&st, &et) >= g_usbio_retry_timeout) { handle->shutdown = true; break; } if (g_usbio_retry_delay > 0) { if ((g_usbio_retry_timeout-time_used) >= g_usbio_retry_delay) { usleep(g_usbio_retry_delay * 1000); time_used += g_usbio_retry_delay; } else { usleep((g_usbio_retry_timeout - time_used) * 1000); time_used = g_usbio_retry_timeout; } } rc = novacom_usb_write(handle, packet.buf, packet.len); count++; } TRACEL(LOG_ALWAYS, "usbll(%08x) writing packet, writes(%ld), duration(%dms), result(%d), last_errno %ld\n", novacom_usbll_getuid(handle->usbll_handle), count, platform_delta_time_msecs(&st, &et), rc, errno); count = 0; } if (rc >=0) { TRACEF/*LOG_PRINTF*/("usbll(%08x) wrote tx packet len=%d\n", novacom_usbll_getuid(handle->usbll_handle), rc); } #if FAULTY_TX } #endif } } LTRACEF("shutting down handle %p\n", handle); platform_event_signal(&handle->tx_shutdown_event); platform_free(buf); return NULL; }
static void *tx_thread_entry(void *arg) { device_pthread_setaffinity(); int rc; int state; struct novacom_tx_packet packet; const struct aiocb * list[1]; list[0] = &txaio; LOG_PRINTF("entry\n"); while (usb_online) { // see if we have something to send packet.len = novacom_usbll_get_mtu(usbll_handle); packet.buf = tx_buffer; state = novacom_usbll_get_state(usbll_handle); if (novacom_usbll_prepare_tx_packet(usbll_handle, &packet, 100) != TX_NO_PACKET) { #if LOCAL_TRACE_RW // write a block back LTRACEF("going to write packet\n"); #endif #if 0 rc = write(ep1in_fd, packet.buf, packet.len); LTRACEF("rc %d\n", rc); if (rc < 0) { TRACEF("error writing packet\n"); break; } #else rc = queue_tx(ep1in_fd, packet.buf, packet.len); if (rc < 0) { LOG_PRINTF("USB aio_write error, ret=%d, errno=%d\n", rc, errno); usleep(1000*GADGETFS_IO_RETRY_DELAY); novacom_usbll_changeback_state(usbll_handle, state); continue; } struct timespec timeout; rc = suspend(list, 1, &timeout); while (rc < 0 && errno == EAGAIN) { LOG_PRINTF("USB aio_suspend (for write) error, ret=%d, errno=%d\n", rc, errno); rc = suspend(list, 1, &timeout); if (rc >= 0) { LOG_PRINTF("USB aio_suspend (for write) ret=%d, errno=%d\n", rc, errno); } }; #if 0 //do we need it ??? if (rc < 0) { LTRACEF("timeout on tx\n"); rc = aio_suspend(list, 1, NULL); } #endif if (aio_error(&txaio) != EINPROGRESS) { rc = aio_return(&txaio); if (rc < 0) { /* online->offline transition */ LOG_PRINTF("USB aio_return (for write) error, ret=%d, \n", rc); if( (usb_online != gadgetfs_online) && (true == usb_online) ) { int ret = platform_event_wait_timeout(&usb_online_event, TRANSPORT_RECOVERY_TIMEOUT * 1000*2); if (!ret) { LOG_PRINTF("platform_event_wait_timeout for usb_online_event, ret=%d\n", ret); } else { LOG_PRINTF("platform_event_wait_timeout for usb_online_event, ret=%d, ignored\n", ret); } } } } else { LOG_PRINTF("we should never enter here (EINPROGRESS=%d), USB aio write seems to have problem!\n", EINPROGRESS); } if (rc < 0) { novacom_usbll_changeback_state(usbll_handle, state); } else { static platform_time_t prior; static int init = 0; static unsigned int tx_bytes = 0, tx_packets = 0; platform_time_t curr; tx_bytes += packet.len; tx_packets++; if (!init) { platform_get_time(&prior); init = 1; } platform_get_time(&curr); if (platform_delta_time_msecs(&prior, &curr) >= 2800) { //logging for every 3sec platform_get_time(&prior); LOG_PRINTF("wrote %u bytes, %u packets\n",tx_bytes, tx_packets); } } #endif } } LOG_PRINTF("shutting down\n"); platform_event_signal(&tx_shutdown_event); return NULL; }