Example #1
0
/* This function is executed in the interrupt context */
static void dma_rx_callback(void *arg, u32_t channel, int status)
{
	struct device *dev = get_dev_from_rx_dma_channel(channel);
	const struct i2s_stm32_cfg *cfg = DEV_CFG(dev);
	struct i2s_stm32_data *const dev_data = DEV_DATA(dev);
	struct stream *stream = &dev_data->rx;
	void *mblk_tmp;
	int ret;

	if (status != 0) {
		ret = -EIO;
		stream->state = I2S_STATE_ERROR;
		goto rx_disable;
	}

	__ASSERT_NO_MSG(stream->mem_block != NULL);

	/* Stop reception if there was an error */
	if (stream->state == I2S_STATE_ERROR) {
		goto rx_disable;
	}

	mblk_tmp = stream->mem_block;

	/* Prepare to receive the next data block */
	ret = k_mem_slab_alloc(stream->cfg.mem_slab, &stream->mem_block,
			       K_NO_WAIT);
	if (ret < 0) {
		stream->state = I2S_STATE_ERROR;
		goto rx_disable;
	}

	ret = reload_dma(dev_data->dev_dma, stream->dma_channel,
			&stream->dma_cfg,
			(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
			stream->mem_block,
			stream->cfg.block_size);
	if (ret < 0) {
		LOG_DBG("Failed to start RX DMA transfer: %d", ret);
		goto rx_disable;
	}

	/* Assure cache coherency after DMA write operation */
	DCACHE_INVALIDATE(mblk_tmp, stream->cfg.block_size);

	/* All block data received */
	ret = queue_put(&stream->mem_block_queue, mblk_tmp,
			stream->cfg.block_size);
	if (ret < 0) {
		stream->state = I2S_STATE_ERROR;
		goto rx_disable;
	}
	k_sem_give(&stream->sem);

	/* Stop reception if we were requested */
	if (stream->state == I2S_STATE_STOPPING) {
		stream->state = I2S_STATE_READY;
		goto rx_disable;
	}

	return;

rx_disable:
	rx_stream_disable(stream, dev);
}
bool Emulator_Implementation_InitSettings()
{
	LOG_DBG("Emulator_Implementation_InitSettings()");

	memset((&Settings), 0, (sizeof(Settings)));

	currentconfig.Clear();

	#ifdef SYS_CONFIG_FILE
		try_load_config_file(SYS_CONFIG_FILE, currentconfig);
	#endif

	//PS3 - General settings	
	if (currentconfig.Exists("PS3General::KeepAspect"))
	{
		Settings.PS3KeepAspect		=	currentconfig.GetBool("PS3General::KeepAspect");
	}
	else
	{
		Settings.PS3KeepAspect		=	true;
	}

	if (currentconfig.Exists("PS3General::Smooth"))
	{
		Settings.PS3Smooth		=	currentconfig.GetBool("PS3General::Smooth");
	}
	else
	{
		Settings.PS3Smooth		=	false;
	}

	if (currentconfig.Exists("PS3General::OverscanEnabled"))
	{
		Settings.PS3OverscanEnabled	= currentconfig.GetBool("PS3General::OverscanEnabled");
	}
	else
	{
		Settings.PS3OverscanEnabled	= false;
	}
	if (currentconfig.Exists("PS3General::OverscanAmount"))
	{
		Settings.PS3OverscanAmount	= currentconfig.GetInt("PS3General::OverscanAmount");
	}
	else
	{
		Settings.PS3OverscanAmount	= 0;
	}

	if (currentconfig.Exists("FCEU::Controlstyle"))
	{
		Settings.FCEUControlstyle = currentconfig.GetInt("FCEU::Controlstyle");
		control_style = (ControlStyle)(((int)Settings.FCEUControlstyle));
	}
	else
	{
		Settings.FCEUControlstyle = CONTROL_STYLE_ORIGINAL;
		control_style = CONTROL_STYLE_ORIGINAL;
	}

	if (currentconfig.Exists("FCEU::DisableSpriteLimitation"))
	{
		Settings.FCEUDisableSpriteLimitation = currentconfig.GetBool("FCEU::DisableSpriteLimitation");
		FCEUI_DisableSpriteLimitation(Settings.FCEUDisableSpriteLimitation);
	}
	else
	{
		Settings.FCEUDisableSpriteLimitation = false;
	}

	if (currentconfig.Exists("PS3General::PS3CurrentShader"))
	{
		Settings.PS3CurrentShader.assign(currentconfig.GetString("PS3General::PS3CurrentShader"));
	}
	else
	{
		Settings.PS3CurrentShader.assign(DEFAULT_SHADER_FILE);
	}

	if (currentconfig.Exists("PS3General::PS3CurrentResolution"))
	{
		Settings.PS3CurrentResolution = currentconfig.GetInt("PS3General::PS3CurrentResolution");
	}
	else
	{
		Settings.PS3CurrentResolution = NULL;
	}

	if (currentconfig.Exists("FCEU::GameGenie"))
	{
		Settings.FCEUGameGenie = currentconfig.GetBool("FCEU::GameGenie");
		FCEUI_SetGameGenie(Settings.FCEUGameGenie);
	}
	else
	{
		Settings.FCEUGameGenie = false;
	}
	FCEUI_SetGameGenie(Settings.FCEUGameGenie);
	if (currentconfig.Exists("PS3General::PS3PALTemporalMode60Hz"))
	{
		Settings.PS3PALTemporalMode60Hz = currentconfig.GetBool("PS3General::PS3PALTemporalMode60Hz");
	}
	else
	{
		Settings.PS3PALTemporalMode60Hz = false;
	}
	//RSound Settings
	if(currentconfig.Exists("RSound::RSoundEnabled"))
	{
		Settings.RSoundEnabled		= currentconfig.GetBool("RSound::RSoundEnabled");
	}
	else
	{
		Settings.RSoundEnabled		= false;
	}
	if(currentconfig.Exists("RSound::RSoundServerIPAddress"))
	{
		Settings.RSoundServerIPAddress	= currentconfig.GetString("RSound::RSoundServerIPAddress");
	}
	else
	{
		Settings.RSoundServerIPAddress = "0.0.0.0";
	}
	if(currentconfig.Exists("PS3General::Throttled"))
	{
		Settings.Throttled		= currentconfig.GetInt("PS3General::Throttled");
	}
	else
	{
		Settings.Throttled		= 1;
	}
	// PS3 Path Settings
	if (currentconfig.Exists("PS3Paths::PathSaveStates"))
	{
		Settings.PS3PathSaveStates		= currentconfig.GetString("PS3Paths::PathSaveStates");
	}
	else
	{
		Settings.PS3PathSaveStates		= USRDIR;
	}
	
	if (currentconfig.Exists("PS3Paths::PathSRAM"))
	{
		Settings.PS3PathSRAM		= currentconfig.GetString("PS3Paths::PathSRAM");
	}
	else
	{
		Settings.PS3PathSRAM		= USRDIR;
	}

	if (currentconfig.Exists("PS3Paths::PathCheats"))
	{
		Settings.PS3PathCheats		= currentconfig.GetString("PS3Paths::PathCheats");
	}
	else
	{
		Settings.PS3PathCheats		= USRDIR;
	}
	
	if (currentconfig.Exists("PS3Paths::PathScreenshots"))
	{
		Settings.PS3PathScreenshots		= currentconfig.GetString("PS3Paths::PathScreenshots");
	}
	else
	{
		Settings.PS3PathScreenshots		= USRDIR;
	}
	
	if (currentconfig.Exists("PS3Paths::PathROMDirectory"))
	{
		Settings.PS3PathROMDirectory		= currentconfig.GetString("PS3Paths::PathROMDirectory");
	}
	else
	{
		Settings.PS3PathROMDirectory		= "/";
	}
	if (currentconfig.Exists("PS3Paths::BaseDirectory"))
	{
		Settings.PS3PathBaseDirectory		= currentconfig.GetString("PS3Paths::PathBaseDirectory");
	}
	else
	{
		Settings.PS3PathBaseDirectory		= USRDIR;
	}
	if (currentconfig.Exists("PS3General::ControlScheme"))
	{
		Settings.ControlScheme = currentconfig.GetInt("PS3General::ControlScheme");
	}
	else
	{
		Settings.ControlScheme = CONTROL_SCHEME_DEFAULT;
	}
	Emulator_Implementation_SwitchControlScheme();

	LOG_DBG("SUCCESS - Emulator_Implementation_InitSettings()");
	return true;
}
Example #3
0
static int eswifi_spi_request(struct eswifi_dev *eswifi, char *cmd, size_t clen,
			      char *rsp, size_t rlen)
{
	struct eswifi_spi_data *spi = eswifi->bus_data;
	unsigned int offset = 0, to_read = SPI_READ_CHUNK_SIZE;
	char tmp[2];
	int err;

	LOG_DBG("cmd=%p (%u byte), rsp=%p (%u byte)", cmd, clen, rsp, rlen);

	/*
	 * CMD/DATA protocol:
	 * 1. Module raises data-ready when ready for **command phase**
	 * 2. Host announces command start by lowering chip-select (csn)
	 * 3. Host write the command (possibly several spi transfers)
	 * 4. Host announces end of command by raising chip-select
	 * 5. Module lowers data-ready signal
	 * 6. Module raises data-ready to signal start of the **data phase**
	 * 7. Host lowers chip-select
	 * 8. Host fetch data as long as data-ready pin is up
	 * 9. Module lowers data-ready to signal the end of the data Phase
	 * 10. Host raises chip-select
	 *
	 * Note:
	 * All commands to the eS-WiFi module must be post-padded with
	 * 0x0A (Line Feed) to an even number of bytes.
	 * All data from eS-WiFi module are post-padded with 0x15(NAK) to an
	 * even number of bytes.
	 */

	if (!cmd) {
		goto data;
	}

	/* CMD/DATA READY signals the Command Phase */
	err = eswifi_spi_wait_cmddata_ready(spi);
	if (err) {
		LOG_ERR("CMD ready timeout\n");
		return err;
	}

	if (clen % 2) { /* Add post-padding if necessary */
		/* cmd is a string so cmd[clen] is 0x00 */
		cmd[clen] = 0x0a;
		clen++;
	}

	eswifi_spi_write(eswifi, cmd, clen);

	/* Our device is flagged with SPI_HOLD_ON_CS|SPI_LOCK_ON, release */
	spi_release(spi->spi_dev, &spi->spi_cfg);

data:
	/* CMD/DATA READY signals the Data Phase */
	err = eswifi_spi_wait_cmddata_ready(spi);
	if (err) {
		LOG_ERR("DATA ready timeout\n");
		return err;
	}

	while (eswifi_spi_cmddata_ready(spi) && to_read) {
		to_read = MIN(rlen - offset, to_read);
		memset(rsp + offset, 0, to_read);
		eswifi_spi_read(eswifi, rsp + offset, to_read);
		offset += to_read;
		k_yield();
	}

	/* Flush remaining data if receiving buffer not large enough */
	while (eswifi_spi_cmddata_ready(spi)) {
		eswifi_spi_read(eswifi, tmp, 2);
		k_sleep(1);
	}

	/* Our device is flagged with SPI_HOLD_ON_CS|SPI_LOCK_ON, release */
	spi_release(spi->spi_dev, &spi->spi_cfg);

	LOG_DBG("success");

	return offset;
}
Example #4
0
int remote_ctrlmsg_recv(struct hostctrl *hc, struct ctrlmsg *cm,
                        struct sockaddr *from, socklen_t from_len)
{
    struct in_addr *fromip = NULL;
    int ret = 0;
     
    if (from) {
        if (from->sa_family == AF_INET)
            fromip = &((struct sockaddr_in *)from)->sin_addr;
        else if (from->sa_family == AF_SERVAL && 
                 from_len > sizeof(struct sockaddr_in)) {
            channel_addr_t *addr = (channel_addr_t *)from;
            
            if (addr->sv_in.in.sin_family == AF_INET) {
                fromip = &addr->sv_in.in.sin_addr;
            }
        }
    }
    
    switch (cm->type) {
    case CTRLMSG_TYPE_REGISTER: {
        struct ctrlmsg_register *cmr = (struct ctrlmsg_register *)cm;

        if (!fromip)
            break;
        
        ret = hc->cbs->service_registration(hc, &cmr->srvid, 
                                            cmr->srvid_flags, 
                                            cmr->srvid_prefix_bits, 
                                            fromip, 
                                            cmr->flags & REG_FLAG_REREGISTER ? 
                                            &cmr->addr : NULL);
        break;
    }
    case CTRLMSG_TYPE_UNREGISTER: {
        struct ctrlmsg_register *cmr = (struct ctrlmsg_register *)cm;

        if (!fromip)
            break;

        ret = hc->cbs->service_unregistration(hc, &cmr->srvid, 
                                              cmr->srvid_flags, 
                                              cmr->srvid_prefix_bits, 
                                              fromip);
        break;
    }
    case CTRLMSG_TYPE_RESOLVE:
        break;
    case CTRLMSG_TYPE_SERVICE_STAT:
        break;
    case CTRLMSG_TYPE_ADD_SERVICE:
        break;
    case CTRLMSG_TYPE_DEL_SERVICE:
        break;
	default:
		LOG_DBG("Received message type %u\n", cm->type);
		break;
	}
        
    return ret;
}
Example #5
0
static void i2c_dw_isr(void *arg)
{
	struct device *port = (struct device *)arg;
	struct i2c_dw_dev_config * const dw = port->driver_data;
	union ic_interrupt_register intr_stat;
	u32_t value;
	int ret = 0;

	volatile struct i2c_dw_registers * const regs =
		(struct i2c_dw_registers *)dw->base_address;

	/* Cache ic_intr_stat for processing, so there is no need to read
	 * the register multiple times.
	 */
	intr_stat.raw = regs->ic_intr_stat.raw;

#if CONFIG_SHARED_IRQ
	/* If using with shared IRQ, this function will be called
	 * by the shared IRQ driver. So check here if the interrupt
	 * is coming from the I2C controller (or somewhere else).
	 */
	if (!intr_stat.raw) {
		return;
	}
#endif

	/*
	 * Causes of an interrupt:
	 *   - STOP condition is detected
	 *   - Transfer is aborted
	 *   - Transmit FIFO is empty
	 *   - Transmit FIFO has overflowed
	 *   - Receive FIFO is full
	 *   - Receive FIFO has overflowed
	 *   - Received FIFO has underrun
	 *   - Transmit data is required (tx_req)
	 *   - Receive data is available (rx_avail)
	 */

	LOG_DBG("I2C: interrupt received");

	/* Check if we are configured as a master device */
	if (regs->ic_con.bits.master_mode) {
		/* Bail early if there is any error. */
		if ((DW_INTR_STAT_TX_ABRT | DW_INTR_STAT_TX_OVER |
		     DW_INTR_STAT_RX_OVER | DW_INTR_STAT_RX_UNDER) &
		    intr_stat.raw) {
			dw->state = I2C_DW_CMD_ERROR;
			goto done;
		}

		/* Check if the RX FIFO reached threshold */
		if (intr_stat.bits.rx_full) {
			_i2c_dw_data_read(port);
		}

		/* Check if the TX FIFO is ready for commands.
		 * TX FIFO also serves as command queue where read requests
		 * are written to TX FIFO.
		 */
		if (intr_stat.bits.tx_empty) {
			if ((dw->xfr_flags & I2C_MSG_RW_MASK)
			    == I2C_MSG_WRITE) {
				ret = _i2c_dw_data_send(port);
			} else {
				_i2c_dw_data_ask(port);
			}

			/* If STOP is not expected, finish processing this
			 * message if there is nothing left to do anymore.
			 */
			if (((dw->xfr_len == 0)
			     && !(dw->xfr_flags & I2C_MSG_STOP))
			    || (ret != 0)) {
				goto done;
			}
		}
	}

	/* STOP detected: finish processing this message */
	if (intr_stat.bits.stop_det) {
		value = regs->ic_clr_stop_det;
		goto done;
	}

	return;

done:
	_i2c_dw_transfer_complete(port);
}
Example #6
0
void WebInterface::worker() {
	/* Backup the stdio streambufs */
	std::streambuf * cin_streambuf  = std::cin.rdbuf();
	std::streambuf * cout_streambuf = std::cout.rdbuf();
	std::streambuf * cerr_streambuf = std::cerr.rdbuf();

	const std::string kw_title(KW_TITLE);
	const std::string kw_head(KW_HEAD);
	const std::string kw_menu(KW_MENU);
	const std::string kw_content(KW_CONTENT);

	FCGX_Request request;

	/* Initialize FastCGI library and request */
	FCGX_Init();
	FCGX_InitRequest(&request, 0, FCGI_FAIL_ACCEPT_ON_INTR);

	LOG_DBG("FastCGI initialization success!");

	while (!stop_flag_) {
		if(FCGX_Accept_r(&request) >= 0) {

			fcgi_streambuf cin_fcgi_streambuf(request.in);
			fcgi_streambuf cout_fcgi_streambuf(request.out);
			fcgi_streambuf cerr_fcgi_streambuf(request.err);

			std::cin.rdbuf(&cin_fcgi_streambuf);
			std::cout.rdbuf(&cout_fcgi_streambuf);
			std::cerr.rdbuf(&cerr_fcgi_streambuf);

			/* getting the uri from the request */
			std::string uri;
			const char *uri_param = FCGX_GetParam("REQUEST_URI", request.envp);
			if(!uri_param) {
				LOG_ERR("Failed to retrieve the request URI environment value!");
				uri = URI_PAGE_ERROR;
			} else {
				uri = uri_param;
			}

			LOG_DBG("Request received: %s", uri.c_str());

			/* Check if URI is a file in the home folder and get the mime of
			 * that file (by extension) */
			std::string path;
			std::string mime = if_file_get_mime(uri, &path);

			if (!mime.empty()) {
				/* This is a file we need to serve */
				StringPtr file_data = Utils::read_file(path);
				std::cout << "Content-type: " << mime << "\r\n\r\n";
				std::cout << *(file_data);

				file_data.reset();
			} else {
				/* Parse the URI */
				std::map<std::string, std::string> uri_data = parseURI(uri);

				LOG_DBG("URI Parsed, page requested: %s",
						uri_data[URI_PAGE].c_str());

				/* Generate and serve the page depending on the URI */
				StringPtr page;
				std::string content_type = "text/html";

				/* Main page requested */
				if (uri_data[URI_PAGE].compare(URI_PAGE_MAIN) == 0) {
					bool success = false;

					/* Check if a command was sent from the client. */
					if (uri_data.find(URI_PAGE_COMMAND) != uri_data.end()) {
						success = add_command(uri_data[URI_PAGE_COMMAND]);
					}

					std::string s;
					/* Check if the request was sent from javascript or pure HTML */
					if(uri_data.find(URI_PAGE_SOURCE) != uri_data.end()) {
						LOG_DBG("This query's source IS javascript: %s, Source: %s",
								uri.c_str(), (uri_data[URI_PAGE_SOURCE]).c_str());
						content_type = "application/json";
						page = generate_command_json(success);
					} else {
						LOG_DBG("This query's source IS NOT javascript: %s", uri.c_str());
						/* Just generate a standard main page */
						page = generate_main_page();
					}
				/* Log page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_LOG) == 0) {
					page = generate_log_page();

				/* Status page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_STATUS) == 0) {
					page = generate_status_page();

				/* Console lines JSON page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_CL) == 0) {
					if (uri_data.find(URI_PAGE_BEFORE) != uri_data.end()) {
						content_type = "application/json";
						page = generate_cljson_before(
								uri_data[URI_PAGE_BEFORE]);
					} else if (uri_data.find(URI_PAGE_AFTER)
							!= uri_data.end()) {
						content_type = "application/json";
						page = generate_cljson_after(uri_data[URI_PAGE_AFTER]);
					} else {
						page = generate_error_page();
					}

				/* Log lines JSON page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_LL) == 0) {
					if (uri_data.find(URI_PAGE_BEFORE) != uri_data.end()) {
						content_type = "application/json";
						page = generate_lljson_before(
								uri_data[URI_PAGE_BEFORE]);
					} else if (uri_data.find(URI_PAGE_AFTER)
							!= uri_data.end()) {
						content_type = "application/json";
						page = generate_lljson_after(uri_data[URI_PAGE_AFTER]);
					} else {
						page = generate_error_page();
					}
				} else {
					page = generate_error_page();
				}

				/* Output the generated page with the correct content type */
				std::cout << "Content-type: " << content_type << "\r\n\r\n";
				std::cout << *(page.get());
			}

		}
		else {
			LOG_TRC("FCGX_Aceept_r returned less than 0!");
		}
	}

	LOG_TRC("Out of accept request loop!");

	// Free request strucure
	FCGX_Finish_r(&request);

	// Flag the thread as not running anymore.
	running_ = false;

	// restore stdio streambufs
	std::cin.rdbuf(cin_streambuf);
	std::cout.rdbuf(cout_streambuf);
	std::cerr.rdbuf(cerr_streambuf);
}
Example #7
0
/*  its the responsibility of the caller to free passwd_file                  */
int DEFAULT_CC
env_set_user(const char *username, char **passwd_file, int display,
             const struct list *env_names, const struct list *env_values)
{
    int error;
    int pw_uid;
    int pw_gid;
    int uid;
    int index;
    int len;
    char *name;
    char *value;
    char *pw_shell;
    char *pw_dir;
    char text[256];

    pw_shell = 0;
    pw_dir = 0;

    error = g_getuser_info(username, &pw_gid, &pw_uid, &pw_shell, &pw_dir, 0);

    if (error == 0)
    {
        g_rm_temp_dir();
        error = g_setgid(pw_gid);

        if (error == 0)
        {
            error = g_initgroups(username, pw_gid);
        }

        if (error == 0)
        {
            uid = pw_uid;
            error = g_setuid(uid);
        }

        g_mk_temp_dir(0);

        if (error == 0)
        {
            g_clearenv();
            g_setenv("SHELL", pw_shell, 1);
            g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1);
            g_setenv("USER", username, 1);
            g_sprintf(text, "%d", uid);
            g_setenv("UID", text, 1);
            g_setenv("HOME", pw_dir, 1);
            g_set_current_dir(pw_dir);
            g_sprintf(text, ":%d.0", display);
            g_setenv("DISPLAY", text, 1);
            g_setenv("XRDP_SESSION", "1", 1);
            if ((env_names != 0) && (env_values != 0) &&
                    (env_names->count == env_values->count))
            {
                for (index = 0; index < env_names->count; index++)
                {
                    name = (char *) list_get_item(env_names, index),
                    value = (char *) list_get_item(env_values, index),
                    g_setenv(name, value, 1);
                }
            }

            if (passwd_file != 0)
            {
                if (0 == g_cfg->auth_file_path)
                {
                    /* if no auth_file_path is set, then we go for
                     $HOME/.vnc/sesman_username_passwd:DISPLAY */
                    if (!g_directory_exist(".vnc"))
                    {
                        if (g_mkdir(".vnc") < 0)
                        {
                            log_message(LOG_LEVEL_ERROR,
                                        "Error creating .vnc directory: %s",
                                        g_get_strerror());
                        }
                    }

                    len = g_snprintf(NULL, 0, "%s/.vnc/sesman_%s_passwd:%d",
                                     pw_dir, username, display);

                    *passwd_file = (char *) g_malloc(len + 1, 1);
                    if (*passwd_file != NULL)
                    {
                        /* Try legacy name first, remove if found */
                        g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd",
                                  pw_dir, username);
                        if (g_file_exist(*passwd_file))
                        {
                            log_message(LOG_LEVEL_WARNING, "Removing insecure "
                                        "password file %s", *passwd_file);
                            g_file_delete(*passwd_file);
                        }

                        g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d",
                                  pw_dir, username, display);
                    }
                }
                else
                {
                    /* we use auth_file_path as requested */
                    len = g_snprintf(NULL, 0, g_cfg->auth_file_path, username);

                    *passwd_file = (char *) g_malloc(len + 1, 1);
                    if (*passwd_file != NULL)
                    {
                        g_sprintf(*passwd_file, g_cfg->auth_file_path, username);
                    }
                }

                if (*passwd_file != NULL)
                {
                    LOG_DBG("pass file: %s", *passwd_file);
                }
            }

            g_free(pw_dir);
            g_free(pw_shell);
        }
    }
    else
    {
        log_message(LOG_LEVEL_ERROR,
                    "error getting user info for user %s",
                    username);
    }

    return error;
}
Example #8
0
static int
vc_watchdog_thread_func(void *v)
{
	while (1) {
		long rc;
		unsigned long msg = WDOG_PING_MSG;
		VCHIQ_ELEMENT_T elem = {
			.data = (void *)&msg,
			.size = sizeof(msg)
		};
		int time_remaining =
			msecs_to_jiffies(WATCHDOG_PING_RATE_MS);

		LOG_DBG("%s: waiting on disable blocker...", __func__);
		if (wait_for_completion_interruptible(
				&vc_wdog_state->wdog_disable_blocker) != 0) {
			flush_signals(current);
			continue;
		}

		LOG_DBG("%s: Waiting for VC to be awake...", __func__);
		/* Ensure we only ping videocore when it's awake. Call use
		 * service in a mode which will not initiate a wakeup */
		vchiq_use_service_no_resume(vc_wdog_state->service_handle);

		if (!atomic_read(&vc_wdog_state->wdog_enabled)) {
			vchiq_release_service(vc_wdog_state->service_handle);
			LOG_DBG("%s: VC watchdog disabled", __func__);
			continue;
		}

		if (mutex_lock_interruptible(&vc_wdog_state->wdog_ping_mutex)
				!= 0) {
			vchiq_release_service(vc_wdog_state->service_handle);
			LOG_DBG("%s: Interrupted waiting for ping", __func__);
			continue;
		}

		LOG_DBG("%s: Pinging videocore", __func__);
		/* ping vc... */
		vchiq_queue_message(vc_wdog_state->service_handle, &elem, 1);

		LOG_DBG("%s: Waiting for ping response", __func__);
		/* ...and wait for the response with a timeout */
		rc = wait_for_completion_interruptible_timeout(
			&vc_wdog_state->wdog_ping_response,
			msecs_to_jiffies(VC_PING_RESPONSE_TIMEOUT_MS));

		if (rc == 0) {
			/* Timed out... BANG! */
			vc_wdog_state->failed_pings++;
			LOG_ERR("%s VideoCore Watchdog timed out!! (%d)",
				__func__, vc_wdog_state->failed_pings);
			if (vc_wdog_state->failed_pings >=
						WATCHDOG_NO_RESPONSE_COUNT)
			BUG();
		} else if (rc < 0)
			LOG_ERR("%s: Interrupted waiting for ping", __func__);
		else {
			LOG_DBG("%s: Ping response received", __func__);
			vc_wdog_state->failed_pings = 0;
		}

		mutex_unlock(&vc_wdog_state->wdog_ping_mutex);

		vchiq_release_service(vc_wdog_state->service_handle);

		LOG_DBG("%s: waiting before pinging again...", __func__);
		/* delay before running again */
		do {
			set_current_state(TASK_INTERRUPTIBLE);
			time_remaining = schedule_timeout(time_remaining);
			if (time_remaining) {
				LOG_ERR("%s interrupted", __func__);
				flush_signals(current);
			}
		} while (time_remaining > 0);
	}

	return 0;
}

static void vc_watchdog_connected_init(void)
{
	int ret = 0;
	VCHIQ_SERVICE_PARAMS_T vchiq_params = {
		.fourcc      = VCHIQ_MAKE_FOURCC('W', 'D', 'O', 'G'),
		.callback    = vc_watchdog_vchiq_callback,
		.version     = VC_WDOG_VERSION,
		.version_min = VC_WDOG_VERSION_MIN
	};

	LOG_INFO("%s: start", __func__);

	/* Initialize and create a VCHIQ connection */
	ret = vchiq_initialise(&vc_wdog_state->initialise_instance);
	if (ret != 0) {
		LOG_ERR("%s: failed to initialise VCHIQ instance (ret=%d)",
				__func__, ret);
		ret = -EIO;
		goto out;
	}
	ret = vchiq_connect(vc_wdog_state->initialise_instance);
	if (ret != 0) {
		LOG_ERR("%s: failed to connect VCHIQ instance (ret=%d)",
				__func__, ret);
		ret = -EIO;
		goto out;
	}

	ret = vchiq_open_service(vc_wdog_state->initialise_instance,
			&vchiq_params, &vc_wdog_state->service_handle);
	if (ret != 0 || (vc_wdog_state->service_handle == 0)) {
		LOG_ERR("%s: failed to add WDOG service: error %d",
				__func__, ret);
		ret = -EPERM;
		goto out;
	}

	vchiq_release_service(vc_wdog_state->service_handle);

	init_completion(&vc_wdog_state->wdog_ping_response);
	mutex_init(&vc_wdog_state->wdog_ping_mutex);
	init_completion(&vc_wdog_state->wdog_disable_blocker);

#ifdef ENABLE_VC_WATCHDOG
	complete_all(&vc_wdog_state->wdog_disable_blocker);
	atomic_set(&vc_wdog_state->wdog_enabled, 1);
#else
	atomic_set(&vc_wdog_state->wdog_enabled, 0);
#endif

	vc_wdog_state->wdog_thread = kthread_create(
		&vc_watchdog_thread_func, NULL, "vc-watchdog");
	if (vc_wdog_state->wdog_thread == NULL)
		LOG_ERR("FATAL: couldn't create thread vc-watchdog");
	else
		wake_up_process(vc_wdog_state->wdog_thread);

out:
	LOG_INFO("%s: end (ret=%d)", __func__, ret);
}

static int vc_watchdog_probe(struct platform_device *p_dev)
{
	int ret = 0;
	LOG_INFO("%s: start", __func__);
	vc_wdog_state = kzalloc(sizeof(struct vc_watchdog_state), GFP_KERNEL);
	if (!vc_wdog_state) {
		ret = -ENOMEM;
		goto exit;
	}

	vc_wdog_state->p_dev = p_dev;

	vc_wdog_state->proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL);
	if (vc_wdog_state->proc_entry == NULL) {
		ret = -EFAULT;
		goto out_efault;
	}
	vc_wdog_state->proc_entry->data = (void *)vc_wdog_state;
	vc_wdog_state->proc_entry->write_proc = vc_watchdog_proc_write;

	vchiq_add_connected_callback(vc_watchdog_connected_init);

	goto exit;

out_efault:
	kfree(vc_wdog_state);
	vc_wdog_state = NULL;
exit:
	LOG_INFO("%s: end, ret=%d", __func__, ret);
	return ret;
}
Example #9
0
static int spi_dw_configure(const struct spi_dw_config *info,
			    struct spi_dw_data *spi,
			    const struct spi_config *config)
{
	u32_t ctrlr0 = 0U;

	LOG_DBG("%p (prev %p)", config, spi->ctx.config);

	if (spi_context_configured(&spi->ctx, config)) {
		/* Nothing to do */
		return 0;
	}

	/* Verify if requested op mode is relevant to this controller */
	if (config->operation & SPI_OP_MODE_SLAVE) {
		if (!(info->op_modes & SPI_CTX_RUNTIME_OP_MODE_SLAVE)) {
			LOG_ERR("Slave mode not supported");
			return -ENOTSUP;
		}
	} else {
		if (!(info->op_modes & SPI_CTX_RUNTIME_OP_MODE_MASTER)) {
			LOG_ERR("Master mode not supported");
			return -ENOTSUP;
		}
	}

	if (config->operation & (SPI_TRANSFER_LSB |
				 SPI_LINES_DUAL | SPI_LINES_QUAD)) {
		LOG_ERR("Unsupported configuration");
		return -EINVAL;
	}

	/* Word size */
	ctrlr0 |= DW_SPI_CTRLR0_DFS(SPI_WORD_SIZE_GET(config->operation));

	/* Determine how many bytes are required per-frame */
	spi->dfs = SPI_WS_TO_DFS(SPI_WORD_SIZE_GET(config->operation));

	/* SPI mode */
	if (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) {
		ctrlr0 |= DW_SPI_CTRLR0_SCPOL;
	}

	if (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) {
		ctrlr0 |= DW_SPI_CTRLR0_SCPH;
	}

	if (SPI_MODE_GET(config->operation) & SPI_MODE_LOOP) {
		ctrlr0 |= DW_SPI_CTRLR0_SRL;
	}

	/* Installing the configuration */
	write_ctrlr0(ctrlr0, info->regs);

	/* At this point, it's mandatory to set this on the context! */
	spi->ctx.config = config;

	if (!spi_dw_is_slave(spi)) {
		/* Baud rate and Slave select, for master only */
		write_baudr(SPI_DW_CLK_DIVIDER(config->frequency), info->regs);
		write_ser(1 << config->slave, info->regs);
	}

	spi_context_cs_configure(&spi->ctx);

	if (spi_dw_is_slave(spi)) {
		LOG_DBG("Installed slave config %p:"
			    " ws/dfs %u/%u, mode %u/%u/%u",
			    config,
			    SPI_WORD_SIZE_GET(config->operation), spi->dfs,
			    (SPI_MODE_GET(config->operation) &
			     SPI_MODE_CPOL) ? 1 : 0,
			    (SPI_MODE_GET(config->operation) &
			     SPI_MODE_CPHA) ? 1 : 0,
			    (SPI_MODE_GET(config->operation) &
			     SPI_MODE_LOOP) ? 1 : 0);
	} else {
		LOG_DBG("Installed master config %p: freq %uHz (div = %u),"
			    " ws/dfs %u/%u, mode %u/%u/%u, slave %u",
			    config, config->frequency,
			    SPI_DW_CLK_DIVIDER(config->frequency),
			    SPI_WORD_SIZE_GET(config->operation), spi->dfs,
			    (SPI_MODE_GET(config->operation) &
			     SPI_MODE_CPOL) ? 1 : 0,
			    (SPI_MODE_GET(config->operation) &
			     SPI_MODE_CPHA) ? 1 : 0,
			    (SPI_MODE_GET(config->operation) &
			     SPI_MODE_LOOP) ? 1 : 0,
			    config->slave);
	}

	return 0;
}
Example #10
0
static struct pdu_ser * pdu_serialize_gfp(gfp_t                       flags,
                                          const const struct serdes * instance,
                                          struct pdu *                pdu,
                                          struct dup_config_entry   * dup_conf,
                                          struct crypto_blkcipher   * blkcipher)
{
        struct pdu_ser *      tmp;
        struct dt_cons *      dt_cons;
        const void *          buffer_data;
        const struct buffer * buffer;
        const struct pci *    pci;
        size_t                size;
        ssize_t               buffer_size;
        ssize_t               blk_size;
        ssize_t               encrypted_size;
        ssize_t               pci_size;
        char *                data;
        pdu_type_t            pdu_type;
        seq_num_t             seq;
        struct buffer *       buf;
        int i;

        if (!pdu_is_ok(pdu))
                return NULL;

        if (!instance)
                return NULL;

        dt_cons = instance->dt_cons;
        ASSERT(dt_cons);

        buffer = pdu_buffer_get_ro(pdu);
        if (!buffer)
                return NULL;

        buffer_data = buffer_data_ro(buffer);
        if (!buffer_data)
                return NULL;

        buffer_size = buffer_length(buffer);
        if (buffer_size <= 0)
                return NULL;

        pci = pdu_pci_get_ro(pdu);
        if (!pci)
                return NULL;

        pdu_type = pci_type(pci);
        if (!pdu_type_is_ok(pdu_type)) {
                LOG_ERR("Wrong PDU type");
                return NULL;
        }

        /* Base PCI size, fields present in all PDUs */
        pci_size = base_pci_size(dt_cons);

        /*
         * These are available in the stack at this point in time
         * Extend if necessary (e.g.) NACKs, SACKs, ...
         * Set size in first switch/case
         */
        switch (pdu_type) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                size = pci_size + dt_cons->seq_num_length + buffer_size;

                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_FC:
                size = pci_size + CTRL_SEQ_NR + fc_pci_size(dt_cons);
                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_ACK:
                size = pci_size + CTRL_SEQ_NR + dt_cons->seq_num_length;
                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_ACK_AND_FC:
                size = pci_size +
                        CTRL_SEQ_NR +
                        fc_pci_size(dt_cons) +
                        dt_cons->seq_num_length;
                if (size <= 0)
                        return NULL;

                break;
        case PDU_TYPE_CACK:
                size = pci_size +
                        2 * CTRL_SEQ_NR +
                        4 * dt_cons->seq_num_length +
                        RATE_LEN;
                if (size <= 0)
                        return NULL;

                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pdu_type);
                return NULL;
        }

        data = rkmalloc(size, flags);
        if (!data)
                return NULL;

        /* Needed for all PDUs */
        if (serialize_base_pci(instance, data, pci, size)) {
                LOG_ERR("Failed to serialize base PCI");
                rkfree(data);
                return NULL;
        }

        /* Do actual serializing in the second switch case */
        switch (pdu_type) {
        case PDU_TYPE_MGMT:
        case PDU_TYPE_DT:
                seq = pci_sequence_number_get(pci);
                memcpy(data + pci_size, &seq, dt_cons->seq_num_length);

                memcpy(data + pci_size + dt_cons->seq_num_length,
                       buffer_data, buffer_size);

                break;
        case PDU_TYPE_FC:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_fc_pci(instance, data, pci,
                                     pci_size + CTRL_SEQ_NR)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_ack_pci(instance, data, pci,
                                      pci_size + CTRL_SEQ_NR)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        case PDU_TYPE_ACK_AND_FC:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_ack_pci(instance, data, pci,
                                      pci_size + CTRL_SEQ_NR) ||
                    serialize_fc_pci(instance, data, pci,
                                     pci_size +
                                     CTRL_SEQ_NR +
                                     dt_cons->seq_num_length)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        case PDU_TYPE_CACK:
                if (serialize_ctrl_seq(instance, data, pci, pci_size) ||
                    serialize_cc_pci(instance, data, pci,
                                     pci_size + CTRL_SEQ_NR)) {
                        rkfree(data);
                        return NULL;
                }

                break;
        default:
                LOG_ERR("Unknown PDU type %02X", pdu_type);
                return NULL;
        }

        buf = buffer_create_with_gfp(flags, data, size);
        if (!buf) {
                rkfree(data);
                return NULL;
        }

        tmp = pdu_ser_create_buffer_with_gfp(flags, buf);
        if (!tmp) {
                rkfree(buf);
                return NULL;
        }

        /* FIXME: this should be moved to specific policy code */
        if (dup_conf != NULL && dup_conf->ttl_policy != NULL){
            if (pdu_ser_head_grow_gfp(flags, tmp, sizeof(u8))) {
                    LOG_ERR("Failed to grow ser PDU");
                    pdu_ser_destroy(tmp);
                    return NULL;
            }

            if (!dup_ttl_set(tmp, pci_ttl(pci))) {
                    LOG_ERR("Could not set TTL");
                    pdu_ser_destroy(tmp);
                    return NULL;
            }

            if (dup_ttl_is_expired(tmp)) {
                    LOG_DBG("TTL is expired, dropping PDU");
                    pdu_ser_destroy(tmp);
                    return NULL;
            }
        }

        /* FIXME: this should be moved to specific policy code */
        if (blkcipher != NULL && dup_conf != NULL
        		&& dup_conf->enable_encryption){
                buf = pdu_ser_buffer(tmp);
                blk_size = crypto_blkcipher_blocksize(blkcipher);
                buffer_size = buffer_length(buf);
                encrypted_size = (buffer_size/blk_size + 1) * blk_size;

                if (pdu_ser_tail_grow_gfp(tmp, encrypted_size - buffer_size)){
                    LOG_ERR("Failed to grow ser PDU");
                    pdu_ser_destroy(tmp);
                    return NULL;
                }

                /* PADDING */
                data = buffer_data_rw(buf);
                for (i=encrypted_size-1; i>buffer_size; i--){
                    data[i] = encrypted_size - buffer_size;
                }

                /* Encrypt */
                if (!dup_encrypt_data(tmp, blkcipher)) {
                	LOG_ERR("Failed to encrypt PDU");
                	pdu_ser_destroy(tmp);
                	return NULL;
                }
        }

        /* FIXME: this should be moved to specific policy code */
        if (dup_conf != NULL && dup_conf->error_check_policy != NULL){
            /* Assuming CRC32 */
            if (pdu_ser_head_grow_gfp(flags, tmp, sizeof(u32))) {
                    LOG_ERR("Failed to grow ser PDU");
                    pdu_ser_destroy(tmp);
                    return NULL;
            }

            if (!dup_chksum_set(tmp)) {
                    LOG_ERR("Failed to add CRC");
                    pdu_ser_destroy(tmp);
                    return NULL;
            }

            ASSERT(dup_chksum_is_ok(tmp));
        }

        return tmp;
}
Example #11
0
File: env.c Project: andyb2000/xrdp
int DEFAULT_CC
env_set_user(char *username, char *passwd_file, int display)
{
    int error;
    int pw_uid;
    int pw_gid;
    int uid;
    char pw_shell[256];
    char pw_dir[256];
    char pw_gecos[256];
    char text[256];

    error = g_getuser_info(username, &pw_gid, &pw_uid, pw_shell, pw_dir,
                           pw_gecos);

    if (error == 0)
    {
        g_rm_temp_dir();
        error = g_setgid(pw_gid);

        if (error == 0)
        {
            error = g_initgroups(username, pw_gid);
        }

        if (error == 0)
        {
            uid = pw_uid;
            error = g_setuid(uid);
        }

        g_mk_temp_dir(0);

        if (error == 0)
        {
            g_clearenv();
            g_setenv("SHELL", pw_shell, 1);
            g_setenv("PATH", "/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin", 1);
            g_setenv("USER", username, 1);
            g_sprintf(text, "%d", uid);
            g_setenv("UID", text, 1);
            g_setenv("HOME", pw_dir, 1);
            g_set_current_dir(pw_dir);
            g_sprintf(text, ":%d.0", display);
            g_setenv("DISPLAY", text, 1);
            g_setenv("LANG", "en_US.UTF-8", 1);

            if (passwd_file != 0)
            {
                if (0 == g_cfg->auth_file_path)
                {
                    /* if no auth_file_path is set, then we go for
                       $HOME/.vnc/sesman_username_passwd */
                    g_mkdir(".vnc");
                    g_sprintf(passwd_file, "%s/.vnc/sesman_%s_passwd", pw_dir, username);
                }
                else
                {
                    /* we use auth_file_path as requested */
                    g_sprintf(passwd_file, g_cfg->auth_file_path, username);
                }

                LOG_DBG("pass file: %s", passwd_file);
            }
        }
    }
    else
    {
        log_message(LOG_LEVEL_ERROR,
                    "error getting user info for user %s", username);
    }

    return error;
}
Example #12
0
static int serialize_base_pci(const struct serdes * instance,
                              char *                data,
                              const struct pci *    pci,
                              size_t                pdu_len)
{
        int              offset;
        address_t        addr;
        cep_id_t         cep;
        qos_id_t         qos;
        pdu_type_t       type;
        pdu_flags_t      flags;
        struct dt_cons * dt_cons;

        ASSERT(instance);
        ASSERT(data);
        ASSERT(pci_is_ok(pci));
        ASSERT(pdu_len);

        dt_cons = instance->dt_cons;
        ASSERT(dt_cons);

        /*
         * Putting 1 as version number for now
         * If another version is needed, this will have to change
         * Always 8 bit long
         */
        offset = 0;
        memcpy(data + offset, &version, VERSION_SIZE);
        offset += VERSION_SIZE;
        LOG_DBG("Serialized version %d, with size %d", version, VERSION_SIZE);

        addr = pci_destination(pci);
        memcpy(data + offset, &addr, dt_cons->address_length);
        offset += dt_cons->address_length;

        addr = pci_source(pci);
        memcpy(data + offset, &addr, dt_cons->address_length);
        offset += dt_cons->address_length;

        qos = pci_qos_id(pci);
        memcpy(data + offset, &qos, dt_cons->qos_id_length);
        offset += dt_cons->qos_id_length;

        cep = pci_cep_source(pci);
        memcpy(data + offset, &cep, dt_cons->cep_id_length);
        offset += dt_cons->cep_id_length;

        cep = pci_cep_destination(pci);
        memcpy(data + offset, &cep, dt_cons->cep_id_length);
        offset += dt_cons->cep_id_length;

        type = pci_type(pci);
        memcpy(data + offset, &type, PDU_TYPE_SIZE);
        offset += PDU_TYPE_SIZE;

        flags = pci_flags_get(pci);
        memcpy(data + offset, &flags, FLAGS_SIZE);
        offset += FLAGS_SIZE;

        memcpy(data + offset, &pdu_len, dt_cons->length_length);
        offset += dt_cons->length_length;

        return 0;
}
Example #13
0
	void DEFAULT_CC
scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)
{
	long data;
	int retries;
	int current_try;
	enum SCP_SERVER_STATES_E e;
	struct SCP_DISCONNECTED_SESSION* slist = 0;
	int scount;
	int end = 0;

	retries = g_cfg->sec.login_retry;
	current_try = retries;

	data = auth_userpass(NULL, s->username, s->password);
	/*LOG_DBG("user: %s\npass: %s", s->username, s->password);*/

	if (!data)
	{
		scp_v1s_mng_deny_connection(c, "Login failed");
		log_message(&(g_cfg->log), LOG_LEVEL_INFO,
				"[MNG] Login failed for user %s. Connection terminated", s->username);
		scp_session_destroy(s);
		auth_end(data);
		return;
	}

	/* testing if login is allowed */
	if (0 == access_login_mng_allowed(s->username))
	{
		scp_v1s_mng_deny_connection(c, "Access to Terminal Server not allowed.");
		log_message(&(g_cfg->log), LOG_LEVEL_INFO,
				"[MNG] User %s not allowed on TS. Connection terminated", s->username);
		scp_session_destroy(s);
		auth_end(data);
		return;
	}

	e = scp_v1s_mng_allow_connection(c, s);

	end = 1;
	while (end)
	{
		switch (e)
		{
			case SCP_SERVER_STATE_MNG_ACTION:
				log_message(&(g_cfg->log), LOG_LEVEL_INFO, "Connection cancelled after session listing");
				break;

			case SCP_SERVER_STATE_MNG_LISTREQ:
				/* list disconnected sessions */
				slist = session_get_byuser(NULL, &scount, SESMAN_SESSION_STATUS_ALL);
				LOG_DBG(&(g_cfg->log), "sessions on TS: %d (slist: %x)", scount, slist);

				if (0 == slist)
				{
					//          e=scp_v1s_connection_error(c, "Internal error");
					log_message(&(g_cfg->log), LOG_LEVEL_INFO, "No sessions on Terminal Server");
					end = 0;
				}
				else
				{
					e = scp_v1s_mng_list_sessions(c, s, scount, slist);
					g_free(slist);
				}

				break;
			default:
				/* we check the other errors */
				parseCommonStates(e, "scp_v1s_mng_list_sessions()");
				end = 0;
				break;
		}
	}

	/* cleanup */
	scp_session_destroy(s);
	auth_end(data);
}
Example #14
0
static void dma_tx_callback(void *arg, u32_t channel, int status)
{
	struct device *dev = get_dev_from_tx_dma_channel(channel);
	const struct i2s_stm32_cfg *cfg = DEV_CFG(dev);
	struct i2s_stm32_data *const dev_data = DEV_DATA(dev);
	struct stream *stream = &dev_data->tx;
	size_t mem_block_size;
	int ret;

	if (status != 0) {
		ret = -EIO;
		stream->state = I2S_STATE_ERROR;
		goto tx_disable;
	}

	__ASSERT_NO_MSG(stream->mem_block != NULL);

	/* All block data sent */
	k_mem_slab_free(stream->cfg.mem_slab, &stream->mem_block);
	stream->mem_block = NULL;

	/* Stop transmission if there was an error */
	if (stream->state == I2S_STATE_ERROR) {
		LOG_ERR("TX error detected");
		goto tx_disable;
	}

	/* Stop transmission if we were requested */
	if (stream->last_block) {
		stream->state = I2S_STATE_READY;
		goto tx_disable;
	}

	/* Prepare to send the next data block */
	ret = queue_get(&stream->mem_block_queue, &stream->mem_block,
			&mem_block_size);
	if (ret < 0) {
		if (stream->state == I2S_STATE_STOPPING) {
			stream->state = I2S_STATE_READY;
		} else {
			stream->state = I2S_STATE_ERROR;
		}
		goto tx_disable;
	}
	k_sem_give(&stream->sem);

	/* Assure cache coherency before DMA read operation */
	DCACHE_CLEAN(stream->mem_block, mem_block_size);

	ret = reload_dma(dev_data->dev_dma, stream->dma_channel,
			&stream->dma_cfg,
			stream->mem_block,
			(void *)LL_SPI_DMA_GetRegAddr(cfg->i2s),
			stream->cfg.block_size);
	if (ret < 0) {
		LOG_DBG("Failed to start TX DMA transfer: %d", ret);
		goto tx_disable;
	}

	return;

tx_disable:
	tx_stream_disable(stream, dev);
}
Example #15
0
int mtk_bt_enable(int flag, void *func_cb)
{
    const char *errstr;
    struct uart_t u;
    int bt_fd = -1;
    
    LOG_TRC();

#ifndef MTK_COMBO_SUPPORT
    bt_hold_wake_lock(1);

    /* In case BT is powered on before test */
    bt_set_power(0);
    
    if(bt_set_power(1) < 0) {
        LOG_ERR("BT power on fails\n");
        return -1;
    }
#endif

    glib_handle = dlopen("libbluetooth_mtk.so", RTLD_LAZY);
    if (!glib_handle){
        LOG_ERR("%s\n", dlerror());
        goto error;
    }
    
    dlerror(); /* Clear any existing error */
    
    mtk = dlsym(glib_handle, "mtk");
    bt_restore = dlsym(glib_handle, "bt_restore");
    write_comm_port = dlsym(glib_handle, "write_comm_port");
    read_comm_port = dlsym(glib_handle, "read_comm_port");
    bt_send_data = dlsym(glib_handle, "bt_send_data");
    bt_receive_data = dlsym(glib_handle, "bt_receive_data");
    
    if ((errstr = dlerror()) != NULL){
        LOG_ERR("Can't find function symbols %s\n", errstr);
        goto error;
    }

#ifndef MTK_COMBO_SUPPORT
    u.flags &= ~FLOW_CTL_MASK;
    u.flags |= FLOW_CTL_SW;
    u.speed = CUST_BT_BAUD_RATE;
#endif

    bt_fd = mtk(-1, &u, NULL);
    if (bt_fd < 0)
        goto error;

    LOG_DBG("BT is enabled success\n");

#ifndef MTK_COMBO_SUPPORT
    bt_register_timer();
    
    /* Create thread to poll EINT event */
    pthread_create(&eint_thr, NULL, bt_eint_monitor, (void*)bt_fd);
    sched_yield();
#endif

    return bt_fd;

error:
    if (glib_handle){
        dlclose(glib_handle);
        glib_handle = NULL;
    }

#ifndef MTK_COMBO_SUPPORT
    bt_set_power(0);
    bt_hold_wake_lock(0);
#endif

    return -1;
}
Example #16
0
static int transceive(struct device *dev,
		      const struct spi_config *config,
		      const struct spi_buf_set *tx_bufs,
		      const struct spi_buf_set *rx_bufs,
		      bool asynchronous,
		      struct k_poll_signal *signal)
{
	const struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;
	u32_t tmod = DW_SPI_CTRLR0_TMOD_TX_RX;
	u32_t reg_data;
	int ret;

	spi_context_lock(&spi->ctx, asynchronous, signal);

	/* Configure */
	ret = spi_dw_configure(info, spi, config);
	if (ret) {
		goto out;
	}

	if (!rx_bufs || !rx_bufs->buffers) {
		tmod = DW_SPI_CTRLR0_TMOD_TX;
	} else if (!tx_bufs || !tx_bufs->buffers) {
		tmod = DW_SPI_CTRLR0_TMOD_RX;
	}

	/* ToDo: add a way to determine EEPROM mode */

	if (tmod >= DW_SPI_CTRLR0_TMOD_RX &&
	    !spi_dw_is_slave(spi)) {
		reg_data = spi_dw_compute_ndf(rx_bufs->buffers,
					      rx_bufs->count,
					      spi->dfs);
		if (reg_data == UINT32_MAX) {
			ret = -EINVAL;
			goto out;
		}

		write_ctrlr1(reg_data, info->regs);
	} else {
		write_ctrlr1(0, info->regs);
	}

	if (spi_dw_is_slave(spi)) {
		/* Enabling MISO line relevantly */
		if (tmod == DW_SPI_CTRLR0_TMOD_RX) {
			tmod |= DW_SPI_CTRLR0_SLV_OE;
		} else {
			tmod &= ~DW_SPI_CTRLR0_SLV_OE;
		}
	}

	/* Updating TMOD in CTRLR0 register */
	reg_data = read_ctrlr0(info->regs);
	reg_data &= ~DW_SPI_CTRLR0_TMOD_RESET;
	reg_data |= tmod;

	write_ctrlr0(reg_data, info->regs);

	/* Set buffers info */
	spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs);

	spi->fifo_diff = 0U;

	/* Tx Threshold */
	spi_dw_update_txftlr(info, spi);

	/* Does Rx thresholds needs to be lower? */
	reg_data = DW_SPI_RXFTLR_DFLT;

	if (spi_dw_is_slave(spi)) {
		if (spi->ctx.rx_len &&
		    spi->ctx.rx_len < DW_SPI_RXFTLR_DFLT) {
			reg_data = spi->ctx.rx_len - 1;
		}
	} else {
		if (spi->ctx.rx_len && spi->ctx.rx_len < DW_SPI_FIFO_DEPTH) {
			reg_data = spi->ctx.rx_len - 1;
		}
	}

	/* Rx Threshold */
	write_rxftlr(reg_data, info->regs);

	/* Enable interrupts */
	reg_data = !rx_bufs ?
		DW_SPI_IMR_UNMASK & DW_SPI_IMR_MASK_RX :
		DW_SPI_IMR_UNMASK;
	write_imr(reg_data, info->regs);

	spi_context_cs_control(&spi->ctx, true);

	LOG_DBG("Enabling controller");
	set_bit_ssienr(info->regs);

	ret = spi_context_wait_for_completion(&spi->ctx);
out:
	spi_context_release(&spi->ctx, ret);

	return ret;
}
Example #17
0
void mtk_bt_op(BT_REQ req, BT_RESULT *result)
{
    result->status = FALSE;
    
    switch(req.op)
    {
      case BT_COLD_OP_GET_ADDR:
      {
          const char *errstr;
          unsigned char nvram[sizeof(ap_nvram_btradio_mt6610_struct)];
          
          LOG_DBG("BT_COLD_OP_GET_ADDR\n");
          
          glib_handle = dlopen("libbluetooth_mtk.so", RTLD_LAZY);
          if (!glib_handle){
              LOG_ERR("%s\n", dlerror());
              return;
          }
          
          dlerror(); /* Clear any existing error */
          
          bt_read_nvram = dlsym(glib_handle, "bt_read_nvram");
          if ((errstr = dlerror()) != NULL){
              LOG_ERR("Can't find function symbols %s\n", errstr);
              dlclose(glib_handle);
              glib_handle = NULL;
              return;
          }
          
          if (bt_read_nvram(nvram) < 0){
              LOG_ERR("Read Nvram data fails\n");
              dlclose(glib_handle);
              glib_handle = NULL;
              return;
          }
          
          result->status = TRUE;
          if (0 == memcmp(nvram, stBtDefault.addr, 6))
          {
              LOG_DBG("Nvram BD address default value\n");
              result->param.addr[0] = 0;  //default address
              memcpy(&result->param.addr[1], nvram, 6);
          }
          else {
              LOG_DBG("Nvram BD address has valid value\n");
              result->param.addr[0] = 1;  //valid address
              memcpy(&result->param.addr[1], nvram, 6);
          }
          
          dlclose(glib_handle);
          glib_handle = NULL;
          break;
      }
      case BT_HOT_OP_SET_FWASSERT:
          LOG_DBG("BT_HOT_OP_SET_FWASSERT\n");
          
      #ifdef MTK_COMBO_SUPPORT
          // req.param.assert.fd should be the fd returned by mtk_bt_enable
          if (req.param.assert.fd < 0){
              LOG_ERR("Invalid bt fd!\n");
              return;
          }
          
          if (ioctl(req.param.assert.fd, COMBO_IOCTL_FW_ASSERT, \
          	        req.param.assert.reason) < 0)
          {
              LOG_ERR("Set COMBO FW ASSERT fails\n");
              return;
          }
          
          result->status = TRUE;
      #else
          LOG_ERR("Operation not supported!\n");
      #endif
          break;
          
      default:
          LOG_DBG("Unknown operation %d\n", req.op);
          break;
    }
    
    return;
}
Example #18
0
static void push_data(struct device *dev)
{
	const struct spi_dw_config *info = dev->config->config_info;
	struct spi_dw_data *spi = dev->driver_data;
	u32_t data = 0U;
	u32_t f_tx;

	DBG_COUNTER_INIT();

	if (spi_context_rx_on(&spi->ctx)) {
		f_tx = DW_SPI_FIFO_DEPTH - read_txflr(info->regs) -
			read_rxflr(info->regs);
		if ((int)f_tx < 0) {
			f_tx = 0U; /* if rx-fifo is full, hold off tx */
		}
	} else {
		f_tx = DW_SPI_FIFO_DEPTH - read_txflr(info->regs);
	}

	while (f_tx) {
		if (spi_context_tx_buf_on(&spi->ctx)) {
			switch (spi->dfs) {
			case 1:
				data = UNALIGNED_GET((u8_t *)
						     (spi->ctx.tx_buf));
				break;
			case 2:
				data = UNALIGNED_GET((u16_t *)
						     (spi->ctx.tx_buf));
				break;
#ifndef CONFIG_ARC
			case 4:
				data = UNALIGNED_GET((u32_t *)
						     (spi->ctx.tx_buf));
				break;
#endif
			}
		} else if (spi_context_rx_on(&spi->ctx)) {
			/* No need to push more than necessary */
			if ((int)(spi->ctx.rx_len - spi->fifo_diff) <= 0) {
				break;
			}

			data = 0U;
		} else if (spi_context_tx_on(&spi->ctx)) {
			data = 0U;
		} else {
			/* Nothing to push anymore */
			break;
		}

		write_dr(data, info->regs);

		spi_context_update_tx(&spi->ctx, spi->dfs, 1);
		spi->fifo_diff++;

		f_tx--;

		DBG_COUNTER_INC();
	}

	if (!spi_context_tx_on(&spi->ctx)) {
		/* prevents any further interrupts demanding TX fifo fill */
		write_txftlr(0, info->regs);
	}

	LOG_DBG("Pushed: %d", DBG_COUNTER_RESULT());
}
Example #19
0
void mtk_bt_op(BT_REQ req, BT_RESULT *result)
{
    result->status = FALSE;
    
    switch(req.op)
    {
      case BT_COLD_OP_GET_ADDR:
      {
        const char *errstr;
        unsigned char nvram[sizeof(ap_nvram_btradio_struct)];
        unsigned char ucDefaultAddr[6] = {0};
        unsigned long chipId;
        
        LOG_DBG("BT_COLD_OP_GET_ADDR\n");
        
        glib_handle = dlopen("libbluetooth_mtk.so", RTLD_LAZY);
        if (!glib_handle){
            LOG_ERR("%s\n", dlerror());
            return;
        }
        
        dlerror(); /* Clear any existing error */
        
        bt_read_nvram = dlsym(glib_handle, "bt_read_nvram");
        bt_get_combo_id = dlsym(glib_handle, "bt_get_combo_id");
        
        if ((errstr = dlerror()) != NULL){
            LOG_ERR("Can't find function symbols %s\n", errstr);
            dlclose(glib_handle);
            glib_handle = NULL;
            return;
        }
        
        if(bt_read_nvram(nvram) < 0){
            LOG_ERR("Read Nvram data fails\n");
            dlclose(glib_handle);
            glib_handle = NULL;
            return;
        }
        
        /* Get combo chip id */
        if(bt_get_combo_id(&chipId) < 0){
            LOG_ERR("Get combo chip id fails\n");
            dlclose(glib_handle);
            glib_handle = NULL;
            return;
        }
        
        dlclose(glib_handle);
        glib_handle = NULL;
        
        switch(chipId)
        {
          case 0x6620:
            memcpy(ucDefaultAddr, stBtDefault_6620.addr, 6);
            break;
          case 0x6628:
            memcpy(ucDefaultAddr, stBtDefault_6628.addr, 6);
            break;
          case 0x6572:
            memcpy(ucDefaultAddr, stBtDefault_6572.addr, 6);
            break;
          case 0x6582:
            memcpy(ucDefaultAddr, stBtDefault_6582.addr, 6);
            break;
          case 0x6592:
            memcpy(ucDefaultAddr, stBtDefault_6592.addr, 6);
            break;
          case 0x6571:
            memcpy(ucDefaultAddr, stBtDefault_6571.addr, 6);
            break;
          case 0x6630:
            memcpy(ucDefaultAddr, stBtDefault_6630.addr, 6);
            break;
          default:
            LOG_ERR("Unknown combo chip id\n");
            return;
        }
        
        result->status = TRUE;
        if (0 == memcmp(nvram, ucDefaultAddr, 6))
        {
            LOG_DBG("Nvram BD address default value\n");
            result->param.addr[0] = 0;  //default address
            memcpy(&result->param.addr[1], nvram, 6);
        }
        else {
            LOG_DBG("Nvram BD address has valid value\n");
            result->param.addr[0] = 1;  //valid address
            memcpy(&result->param.addr[1], nvram, 6);
        }
        break;
      }
      case BT_HOT_OP_SET_FWASSERT:
      {
        LOG_DBG("BT_HOT_OP_SET_FWASSERT\n");
        
        // req.param.assert.fd should be the fd returned by mtk_bt_enable
        if (req.param.assert.fd < 0){
            LOG_ERR("Invalid bt fd!\n");
            return;
        }
        
        if (ioctl(req.param.assert.fd, COMBO_IOCTL_FW_ASSERT, \
            req.param.assert.reason) < 0){
            LOG_ERR("Set COMBO FW ASSERT fails\n");
            return;
        }
        
        result->status = TRUE;
        break;
      }
      case BT_AUDIO_OP_GET_CONFIG:
      {
        const char *errstr;
        unsigned long chipId;
        int i;
        
        LOG_DBG("BT_AUDIO_OP_GET_CONFIG\n");
        
        glib_handle = dlopen("libbluetooth_mtk.so", RTLD_LAZY);
        if (!glib_handle){
            LOG_ERR("%s\n", dlerror());
            return;
        }
        
        dlerror(); /* Clear any existing error */
        
        bt_get_combo_id = dlsym(glib_handle, "bt_get_combo_id");
        
        if ((errstr = dlerror()) != NULL){
            LOG_ERR("Can't find function symbols %s\n", errstr);
            dlclose(glib_handle);
            glib_handle = NULL;
            return;
        }
        
        /* Get combo chip id */
        if(bt_get_combo_id(&chipId) < 0){
            LOG_ERR("Get combo chip id fails\n");
            dlclose(glib_handle);
            glib_handle = NULL;
            return;
        }
        
        dlclose(glib_handle);
        glib_handle = NULL;
        
        /* Return the specific audio config on current chip */
        for(i = 0; audio_conf_map[i].chip_id; i++){
            if(audio_conf_map[i].chip_id == chipId){
                memcpy(&result->param.audio_conf, &audio_conf_map[i].audio_conf, 
                    sizeof(AUDIO_CONFIG));
                result->status = TRUE;
                return;
            }
        }
        
        result->status = FALSE;
        break;
      }
      default:
        LOG_DBG("Unknown operation %d\n", req.op);
        break;
    }
    
    return;
}
Example #20
0
/*
 * kernel_recv
 * @rq: the newly allocated request from kernel
 *
 * Read requests from the kernel and allocate space for the new request.
 * If there is no request from the kernel, *rq is NULL.
 *
 * This function is not thread safe due to returned stack pointer.  In fact,
 * the returned pointer must not be in-use when this function is called again.
 *
 * Returns: 0 on success, -EXXX on error
 */
static int kernel_recv(struct clog_request **rq)
{
	int r = 0;
	ssize_t len;
	char *foo;
	struct cn_msg *msg;
	struct dm_ulog_request *u_rq;
	struct nlmsghdr *nlmsg_h;

	*rq = NULL;
	memset(recv_buf, 0, sizeof(recv_buf));

	len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
	if (len < 0) {
		LOG_ERROR("Failed to recv message from kernel");
		r = -errno;
		goto fail;
	}

	nlmsg_h = (struct nlmsghdr *)recv_buf;
	switch (nlmsg_h->nlmsg_type) {
	case NLMSG_ERROR:
		LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
		r = -EBADE;
		goto fail;
	case NLMSG_DONE:
		msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
		len -= (ssize_t)sizeof(struct nlmsghdr);

		if (len < (ssize_t)sizeof(struct cn_msg)) {
			LOG_ERROR("Incomplete request from kernel received");
			r = -EBADE;
			goto fail;
		}

		if (msg->len > DM_ULOG_REQUEST_SIZE) {
			LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
				  msg->len, DM_ULOG_REQUEST_SIZE);
			r = -EBADE;
			goto fail;
		}

		if (!msg->len)
			LOG_ERROR("Zero length message received");

		len -= (ssize_t)sizeof(struct cn_msg);

		if (len < msg->len)
			LOG_ERROR("len = %zd, msg->len = %" PRIu16, len, msg->len);

		msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
		u_rq = (struct dm_ulog_request *)msg->data;

		if (!u_rq->request_type) {
			LOG_DBG("Bad transmission, requesting resend [%u]",
				msg->seq);
			r = -EAGAIN;

			if (kernel_ack(msg->seq, EAGAIN)) {
				LOG_ERROR("Failed to NACK kernel transmission [%u]",
					  msg->seq);
				r = -EBADE;
			}
		}

		/*
		 * Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
		 * worth of space that precede the request structure from the
		 * kernel.  Since that space isn't going to be used again, we
		 * can take it for our purposes; rather than allocating a whole
		 * new structure and doing a memcpy.
		 *
		 * We should really make sure 'clog_request' doesn't grow
		 * beyond what is available to us, but we need only check it
		 * once... perhaps at compile time?
		 */
		foo = (char *)u_rq;
		foo -= (sizeof(struct clog_request) - sizeof(struct dm_ulog_request));
		*rq = (struct clog_request *) foo;

		/* Clear the wrapper container fields */
		memset(*rq, 0, (size_t)((char *)u_rq - (char *)(*rq)));
		break;
	default:
		LOG_ERROR("Unknown nlmsg_type");
		r = -EBADE;
	}

fail:
	if (r)
		*rq = NULL;

	return (r == -EAGAIN) ? 0 : r;
}
Example #21
0
//DY : FIX_ME : missing most of the validity controls
//examples (of missing controls):
//should start with "/"
//'{' and '}' should match, '}' can not come first, etc
//
static bool match_addresses(ConnectionState_t* pConnectionState, const char* pPattern, char* pAddress)
{
  bool bMatchAll = false;
  bool bReturnValue = true;
  uint16_t nPatternIndex = 0;
  uint16_t nAddressIndex = 0;

  LOG_DBG("match_addresses -->\n pPattern:%s pAddress:%s\n", pPattern, pAddress);

  while ( bReturnValue )
  {
    if ( pPattern[nPatternIndex] && pAddress[nAddressIndex] )
    {
      if ( pPattern[nPatternIndex] == '{' )
      {
        bMatchAll = true;
        nPatternIndex++;
        continue;
      }
      else
      {
        if ( bMatchAll == false ) //normal comparison
        {
          if ( pPattern[nPatternIndex] != pAddress[nAddressIndex] )
          {
            bReturnValue = false;
          }

          ++nPatternIndex;
          ++nAddressIndex;
        }
        else
        {
          char temp[20]; temp[0] = 0;
          char temp2[20]; temp2[0] = 0;

          LOG_DBG("nPatternIndex %d pPattern+index %s \n", nPatternIndex, pPattern + nPatternIndex );

  //          sscanf( pPattern + nPatternIndex, "%[^}]",temp);
  //          LOG_DBG("pPattern brace ici %s\n",temp);
  //          //DY : buraya bi kontrol konabilir, scanf okuyabilmisse anca (return 1 ise) strlen yaparsin mesela
  //          nPatternIndex += strlen( temp );
  //          sscanf( pAddress + nAddressIndex, "%[^/]",temp2);
  //          LOG_DBG("adress slashe kadar %s\n",temp2);
  //          nAddressIndex += strlen( temp2 );

          char* pEndOfPatternArg = strchr(pPattern + nPatternIndex, '}');

          //DY : FIX_ME : '}' yoksa ne bok yiyecek bu program?
          if ( pEndOfPatternArg )
          {
            uint8_t nNumOfAttrs = pConnectionState->userData.numOfAttrs;

            bMatchAll = false;
            uint16_t nPatternArgLen = pEndOfPatternArg - ( pPattern + nPatternIndex );

            strncpy(temp, pPattern + nPatternIndex ,nPatternArgLen );
            temp[nPatternArgLen] = 0;

            nPatternIndex += ( nPatternArgLen + 1 ); // +1 is for consuming '}' character as well.

            LOG_DBG("pPattern brace ici %s new pPattern index %d endofarg %s\n", temp, nPatternIndex, pEndOfPatternArg );

            if ( nNumOfAttrs < MAX_URL_MATCHED_ATTRS )
            {
              pConnectionState->userData.attributes[nNumOfAttrs].pattern = http_server_put_in_conn_buffer(pConnectionState, temp);

              LOG_DBG("pattern %s\n", pConnectionState->userData.attributes[nNumOfAttrs].pattern);

              char* pEndOfAddressArg = strchr(pAddress + nAddressIndex, '/');

              if ( pEndOfAddressArg )
              {
                uint16_t nAddressArgLen = pEndOfAddressArg - ( pAddress + nAddressIndex );

                strncpy(temp, pAddress + nAddressIndex ,nAddressArgLen );
                temp[nAddressArgLen] = 0;

                nAddressIndex += nAddressArgLen;

                LOG_DBG("address1 / ici %s new adress index %d\n", temp, nAddressIndex);

                pConnectionState->userData.attributes[nNumOfAttrs].realValue = http_server_put_in_conn_buffer(pConnectionState, temp);
                pConnectionState->userData.numOfAttrs++;

                LOG_DBG("address1 real value %s\n", pConnectionState->userData.attributes[pConnectionState->userData.numOfAttrs-1].realValue);
              }
              else
              {
                strcpy(temp, pAddress + nAddressIndex );

                nAddressIndex += strlen(temp);

                LOG_DBG("address2 / ici %s new adress index %d paddress %s\n", temp, nAddressIndex, pAddress );

                pConnectionState->userData.attributes[nNumOfAttrs].realValue = http_server_put_in_conn_buffer(pConnectionState, temp);
                pConnectionState->userData.numOfAttrs++;
              }
            }
            else
            {
              LOG_ERR("MAX_URL_MATCHED_ATTRS(%d) is exceeded!!\n", MAX_URL_MATCHED_ATTRS);
            }
          }
        }
      }
    }
    //added just the handle the last '/' character in which only one of the urls may have but still they are matching
    //DY : FIX_ME : buna baska bi cozum bul, bole c*k gereksiz ve kotu oldu.
    else
    {
      if ( pPattern[nPatternIndex] )
      {
        //if url still has more characters or current character is not '/' then urls do not match
        if ( pPattern[nPatternIndex] != '/' || strlen(pPattern) != ++nPatternIndex )
        {
          bReturnValue = false;
        }
      }
      else if ( pAddress[nAddressIndex] )
      {
       if ( pAddress[nAddressIndex] != '/' || strlen(pAddress) != ++nAddressIndex )
        {
          bReturnValue = false;
        }
      }
      //if both urls finished, then they match, just get out of the loop
      else
      {
        //strings are equal so just stop
        break;
      }
    }
  }

  LOG_DBG("Match Addresses Result %d\n",bReturnValue);

  return bReturnValue;
}
Example #22
0
void* DEFAULT_CC
scp_process_start(void* sck)
{
    struct SCP_CONNECTION scon;
    struct SCP_SESSION* sdata;

    /* making a local copy of the socket (it's on the stack) */
    /* probably this is just paranoia                        */
    scon.in_sck = thread_sck;
    LOG_DBG(&(g_cfg.log), "started scp thread on socket %d", scon.in_sck);

    /* unlocking thread_sck */
    lock_socket_release();

    make_stream(scon.in_s);
    make_stream(scon.out_s);

    init_stream(scon.in_s, 8192);
    init_stream(scon.out_s, 8192);

    switch (scp_vXs_accept(&scon, &(sdata)))
    {
    case SCP_SERVER_STATE_OK:
        if (sdata->version == 0)
        {
            /* starts processing an scp v0 connection */
            LOG_DBG(&(g_cfg.log), "accept ok, go on with scp v0\n",0);
            scp_v0_process(&scon, sdata);
        }
        else
        {
            LOG_DBG(&(g_cfg.log), "accept ok, go on with scp v1\n",0);
            /*LOG_DBG(&(g_cfg.log), "user: %s\npass: %s",sdata->username, sdata->password);*/
            scp_v1_process(&scon, sdata);
        }
        break;
    case SCP_SERVER_STATE_START_MANAGE:
        /* starting a management session */
        log_message(&(g_cfg.log), LOG_LEVEL_WARNING,
                    "starting a sesman management session...");
//      scp_v1s_mng_process(&scon, sdata);
        break;
    case SCP_SERVER_STATE_VERSION_ERR:
        /* an unknown scp version was requested, so we shut down the */
        /* connection (and log the fact)                             */
        log_message(&(g_cfg.log), LOG_LEVEL_WARNING,
                    "unknown protocol version specified. connection refused.");
        break;
    case SCP_SERVER_STATE_NETWORK_ERR:
        log_message(&(g_cfg.log), LOG_LEVEL_WARNING, "libscp network error.");
        break;
    case SCP_SERVER_STATE_SEQUENCE_ERR:
        log_message(&(g_cfg.log), LOG_LEVEL_WARNING, "libscp sequence error.");
        break;
    case SCP_SERVER_STATE_INTERNAL_ERR:
        /* internal error occurred (eg. malloc() error, ecc.) */
        log_message(&(g_cfg.log), LOG_LEVEL_ERROR, "libscp internal error occurred.");
        break;
    default:
        log_message(&(g_cfg.log), LOG_LEVEL_ALWAYS, "unknown return from scp_vXs_accept()");
    }
    g_tcp_close(scon.in_sck);
    free_stream(scon.in_s);
    free_stream(scon.out_s);
    return 0;
}
Example #23
0
int
common_sender_inactivity_timer(struct dtp_ps * ps)
{
        struct dtp *         dtp = ps->dm;
        struct dt *          dt;
        struct dtcp *        dtcp;
        struct dtcp_ps *     dtcp_ps;
        struct dtcp_config * cfg;
        seq_num_t            max_sent, snd_rt_win, init_credit, next_send;

        LOG_DBG("default_sender_inactivity launched");

        if (!dtp) return 0;

        dt = dtp_dt(dtp);
        if (!dt)
                return -1;

        dtcp = dt_dtcp(dt);
        if (!dtp)
                return -1;

        dt_sv_drf_flag_set(dt, true);
        dtp_initial_sequence_number(dtp);

        cfg = dtcp_config_get(dtcp);
        if (!cfg)
                return -1;

        rcu_read_lock();
        dtcp_ps = dtcp_ps_get(dtcp);

        if (dtcp_ps->rtx_ctrl) {
                struct rtxq * q;

                q = dt_rtxq(dt);
                if (!q) {
                        rcu_read_unlock();
                        LOG_ERR("Couldn't find the Retransmission queue");
                        return -1;
                }
                rtxq_flush(q);
        }
        if (dtcp_ps->flow_ctrl) {
                struct cwq * cwq;

                cwq = dt_cwq(dt);
                ASSERT(cwq);
                if (cwq_flush(cwq)) {
                        rcu_read_unlock();
                        LOG_ERR("Coudln't flush cwq");
                        return -1;
                }
                dt_sv_window_closed_set(dt, false);
        }
        rcu_read_unlock();

        init_credit = dtcp_initial_credit(cfg);
        max_sent    = dtp_sv_max_seq_nr_sent(dtp);
        snd_rt_win  = dtcp_snd_rt_win(dtcp);
        next_send   = dtp_sv_last_nxt_seq_nr(dtp);

        LOG_DBG("Current values:\n\tinit_credit: %u "
                "max_sent: %u snd_rt_win: %u next_send: %u",
                init_credit, max_sent, snd_rt_win, next_send);

        dtcp_snd_rt_win_set(dtcp, next_send + init_credit);
        LOG_DBG("Resulting snd_rt_win_edge: %u", dtcp_snd_rt_win(dtcp));

        /*FIXME: Missing sending the control ack pdu */
        return 0;
}
Example #24
0
int dtcp_set_policy_set_param(struct dtcp * dtcp,
                              const char * path,
                              const char * name,
                              const char * value)
{
        struct dtcp_ps *ps;
        int ret = -1;

        if (!dtcp|| !path || !name || !value) {
                LOG_ERRF("NULL arguments %p %p %p %p",
                         dtcp, path, name, value);
                return -1;
        }

        LOG_DBG("set-policy-set-param '%s' '%s' '%s'", path, name, value);

        if (strcmp(path, "") == 0) {
                int bool_value;

                /* The request addresses this DTCP instance. */
                rcu_read_lock();
                ps = container_of(rcu_dereference(dtcp->base.ps),
                                  struct dtcp_ps,
                                  base);
                if (strcmp(name, "flow_ctrl") == 0) {
                        ret = kstrtoint(value, 10, &bool_value);
                        if (ret == 0) {
                                ps->flow_ctrl = bool_value;
                        }
                } else if (strcmp(name, "rtx_ctrl") == 0) {
                        ret = kstrtoint(value, 10, &bool_value);
                        if (ret == 0) {
                                ps->rtx_ctrl = bool_value;
                        }
                } else if (strcmp(name, "flowctrl.window_based") == 0) {
                        ret = kstrtoint(value, 10, &bool_value);
                        if (ret == 0) {
                                ps->flowctrl.window_based = bool_value;
                        }
                } else if (strcmp(name, "flowctrl.rate_based") == 0) {
                        ret = kstrtoint(value, 10, &bool_value);
                        if (ret == 0) {
                                ps->flowctrl.rate_based = bool_value;
                        }
                } else if (strcmp(name, "flowctrl.sent_bytes_th") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.sent_bytes_th);
                } else if (strcmp(name, "flowctrl.sent_bytes_percent_th")
                                == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.sent_bytes_percent_th);
                } else if (strcmp(name, "flowctrl.sent_buffers_th") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.sent_buffers_th);
                } else if (strcmp(name, "flowctrl.rcvd_bytes_th") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.rcvd_bytes_th);
                } else if (strcmp(name, "flowctrl.rcvd_bytes_percent_th")
                                == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.rcvd_bytes_percent_th);
                } else if (strcmp(name, "flowctrl.rcvd_buffers_th") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.rcvd_buffers_th);
                } else if (strcmp(name, "rtx.max_time_retry") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->rtx.max_time_retry);
                } else if (strcmp(name, "rtx.data_retransmit_max") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->rtx.data_retransmit_max);
                } else if (strcmp(name, "rtx.initial_tr") == 0) {
                        ret = kstrtouint(value, 10, &ps->rtx.initial_tr);
                } else if (strcmp(name,
                                "flowctrl.window.max_closed_winq_length")
                                        == 0) {
                        ret = kstrtouint(value, 10,
                                &ps->flowctrl.window.max_closed_winq_length);
                } else if (strcmp(name, "flowctrl.window.initial_credit")
                                == 0) {
                        ret = kstrtouint(value, 10,
                                &ps->flowctrl.window.initial_credit);
                } else if (strcmp(name, "flowctrl.rate.sending_rate") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.rate.sending_rate);
                } else if (strcmp(name, "flowctrl.rate.time_period") == 0) {
                        ret = kstrtouint(value, 10,
                                         &ps->flowctrl.rate.time_period);
                } else {
                        LOG_ERR("Unknown DTP parameter policy '%s'", name);
                }
                rcu_read_unlock();

        } else {
Example #25
0
static int _i2c_dw_setup(struct device *dev, u16_t slave_address)
{
	struct i2c_dw_dev_config * const dw = dev->driver_data;
	u32_t value;
	union ic_con_register ic_con;
	volatile struct i2c_dw_registers * const regs =
		(struct i2c_dw_registers *)dw->base_address;

	ic_con.raw = 0U;

	/* Disable the device controller to be able set TAR */
	regs->ic_enable.bits.enable = 0U;

	/* Disable interrupts */
	regs->ic_intr_mask.raw = 0U;

	/* Clear interrupts */
	value = regs->ic_clr_intr;

	/* Set master or slave mode - (initialization = slave) */
	if (I2C_MODE_MASTER & dw->app_config) {
		/*
		 * Make sure to set both the master_mode and slave_disable_bit
		 * to both 0 or both 1
		 */
		LOG_DBG("I2C: host configured as Master Device");
		ic_con.bits.master_mode = 1U;
		ic_con.bits.slave_disable = 1U;
	} else {
		return -EINVAL;
	}

	ic_con.bits.restart_en = 1U;

	/* Set addressing mode - (initialization = 7 bit) */
	if (I2C_ADDR_10_BITS & dw->app_config) {
		LOG_DBG("I2C: using 10-bit address");
		ic_con.bits.addr_master_10bit = 1U;
		ic_con.bits.addr_slave_10bit = 1U;
	}

	/* Setup the clock frequency and speed mode */
	switch (I2C_SPEED_GET(dw->app_config)) {
	case I2C_SPEED_STANDARD:
		LOG_DBG("I2C: speed set to STANDARD");
		regs->ic_ss_scl_lcnt = dw->lcnt;
		regs->ic_ss_scl_hcnt = dw->hcnt;
		ic_con.bits.speed = I2C_DW_SPEED_STANDARD;

		break;
	case I2C_SPEED_FAST:
		/* fall through */
	case I2C_SPEED_FAST_PLUS:
		LOG_DBG("I2C: speed set to FAST or FAST_PLUS");
		regs->ic_fs_scl_lcnt = dw->lcnt;
		regs->ic_fs_scl_hcnt = dw->hcnt;
		ic_con.bits.speed = I2C_DW_SPEED_FAST;

		break;
	case I2C_SPEED_HIGH:
		if (!dw->support_hs_mode) {
			return -EINVAL;
		}

		LOG_DBG("I2C: speed set to HIGH");
		regs->ic_hs_scl_lcnt = dw->lcnt;
		regs->ic_hs_scl_hcnt = dw->hcnt;
		ic_con.bits.speed = I2C_DW_SPEED_HIGH;

		break;
	default:
		LOG_DBG("I2C: invalid speed requested");
		return -EINVAL;
	}

	LOG_DBG("I2C: lcnt = %d", dw->lcnt);
	LOG_DBG("I2C: hcnt = %d", dw->hcnt);

	/* Set the IC_CON register */
	regs->ic_con = ic_con;

	/* Set RX fifo threshold level.
	 * Setting it to zero automatically triggers interrupt
	 * RX_FULL whenever there is data received.
	 *
	 * TODO: extend the threshold for multi-byte RX.
	 */
	regs->ic_rx_tl = 0U;

	/* Set TX fifo threshold level.
	 * TX_EMPTY interrupt is triggered only when the
	 * TX FIFO is truly empty. So that we can let
	 * the controller do the transfers for longer period
	 * before we need to fill the FIFO again. This may
	 * cause some pauses during transfers, but this keeps
	 * the device from interrupting often.
	 */
	regs->ic_tx_tl = 0U;

	if (regs->ic_con.bits.master_mode) {
		/* Set address of target slave */
		regs->ic_tar.bits.ic_tar = slave_address;
	} else {
		/* Set slave address for device */
		regs->ic_sar.bits.ic_sar = slave_address;
	}

	/* If I2C is being operated in master mode and I2C_DYNAMIC_TAR_UPDATE
	 * configuration parameter is set to Yes (1), the ic_10bitaddr_master
	 * bit in ic_tar register would control whether the DW_apb_i2c starts
	 * its transfers in 7-bit or 10-bit addressing mode.
	 */
	if (I2C_MODE_MASTER & dw->app_config) {
		if (I2C_ADDR_10_BITS & dw->app_config) {
			regs->ic_tar.bits.ic_10bitaddr_master = 1U;
		} else {
			regs->ic_tar.bits.ic_10bitaddr_master = 0U;
		}
	}

	return 0;
}
Example #26
0
int dtcp_common_rcv_control(struct dtcp * dtcp, struct pdu * pdu)
{
        struct dtcp_ps * ps;
        struct pci *     pci;
        pdu_type_t       type;
        seq_num_t        sn;
        seq_num_t        last_ctrl;
        int              ret;

        LOG_DBG("dtcp_common_rcv_control called");

        if (!pdu_is_ok(pdu)) {
                LOG_ERR("PDU is not ok");
                pdu_destroy(pdu);
                return -1;
        }

        if (!dtcp) {
                LOG_ERR("DTCP instance bogus");
                pdu_destroy(pdu);
                return -1;
        }

        atomic_inc(&dtcp->cpdus_in_transit);

        pci = pdu_pci_get_rw(pdu);
        if (!pci_is_ok(pci)) {
                LOG_ERR("PCI couldn't be retrieved");
                atomic_dec(&dtcp->cpdus_in_transit);
                pdu_destroy(pdu);
                return -1;
        }

        type = pci_type(pci);

        if (!pdu_type_is_control(type)) {
                LOG_ERR("CommonRCVControl policy received a non-control PDU");
                atomic_dec(&dtcp->cpdus_in_transit);
                pdu_destroy(pdu);
                return -1;
        }

        sn = pci_sequence_number_get(pci);
        last_ctrl = last_rcv_ctrl_seq(dtcp);

        if (sn <= last_ctrl) {
                switch (type) {
                case PDU_TYPE_FC:
                        flow_ctrl_inc(dtcp);
                        break;
                case PDU_TYPE_ACK:
                        acks_inc(dtcp);
                        break;
                case PDU_TYPE_ACK_AND_FC:
                        acks_inc(dtcp);
                        flow_ctrl_inc(dtcp);
                        break;
                default:
                        break;
                }

                pdu_destroy(pdu);
                return 0;

        }
        rcu_read_lock();
        ps = container_of(rcu_dereference(dtcp->base.ps),
                          struct dtcp_ps, base);
        if (sn > (last_ctrl + 1)) {
                ps->lost_control_pdu(ps);
        }
        rcu_read_unlock();

        /* We are in sn >= last_ctrl + 1 */

        last_rcv_ctrl_seq_set(dtcp, sn);

        LOG_DBG("dtcp_common_rcv_control sending to proper function...");

        switch (type) {
        case PDU_TYPE_ACK:
                ret = rcv_ack(dtcp, pdu);
                break;
        case PDU_TYPE_NACK:
                ret = rcv_nack_ctl(dtcp, pdu);
                break;
        case PDU_TYPE_FC:
                ret = rcv_flow_ctl(dtcp, pdu);
                break;
        case PDU_TYPE_ACK_AND_FC:
                ret = rcv_ack_and_flow_ctl(dtcp, pdu);
                break;
        default:
                ret = -1;
                break;
        }

        atomic_dec(&dtcp->cpdus_in_transit);
        return ret;
}
Example #27
0
VC_VCHI_FB_HANDLE_T vc_vchi_fb_init(VCHI_INSTANCE_T vchi_instance,
				    VCHI_CONNECTION_T **vchi_connections,
				    uint32_t num_connections)
{
	uint32_t i;
	FB_INSTANCE_T *instance;
	int32_t status;

	LOG_DBG("%s: start", __func__);

	if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
		LOG_ERR("%s: unsupported number of connections %u (max=%u)",
			__func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);

		return NULL;
	}
	/* Allocate memory for this instance */
	instance = kzalloc(sizeof(*instance), GFP_KERNEL);
	memset(instance, 0, sizeof(*instance));

	instance->num_connections = num_connections;

	/* Create the message available semaphore */
	sema_init(&instance->msg_avail, 0);

	/* Create a lock for exclusive, serialized VCHI connection access */
	mutex_init(&instance->vchi_mutex);

	/* Open the VCHI service connections */
	for (i = 0; i < num_connections; i++) {
		SERVICE_CREATION_T params = {
			VCHI_VERSION_EX(VC_FB_VER, VC_FB_VER_MIN),
			VC_FB_SERVER_NAME,
			vchi_connections[i],
			0,
			0,
			fb_vchi_callback,
			instance,
			0,
			0,
			0
		};

		status = vchi_service_open(vchi_instance, &params,
					   &instance->vchi_handle[i]);
		if (status) {
			LOG_ERR
			    ("%s: failed to open VCHI service (%d)",
			     __func__, status);

			goto err_close_services;
		}
		/* Finished with the service for now */
		vchi_service_release(instance->vchi_handle[i]);
	}

	return instance;

err_close_services:
	for (i = 0; i < instance->num_connections; i++)
		vchi_service_close(instance->vchi_handle[i]);

	kfree(instance);

	return NULL;
}
Example #28
0
pdu_type_t pdu_ctrl_type_get(struct dtcp * dtcp, seq_num_t seq)
{
        struct dtcp_config * dtcp_cfg;
        struct dtcp_ps *ps;
        bool flow_ctrl;
        seq_num_t    LWE;
        timeout_t    a;

        if (!dtcp) {
                LOG_ERR("No DTCP passed...");
                return -1;
        }

        if (!dtcp->parent) {
                LOG_ERR("No DTCP parent passed...");
                return -1;
        }

        dtcp_cfg = dtcp_config_get(dtcp);
        ASSERT(dtcp_cfg);

        rcu_read_lock();
        ps = container_of(rcu_dereference(dtcp->base.ps),
                          struct dtcp_ps, base);
        flow_ctrl = ps->flow_ctrl;
        rcu_read_unlock();

        a = dt_sv_a(dtcp->parent);

        LWE = dt_sv_rcv_lft_win(dtcp->parent);
        if (last_snd_data_ack(dtcp) < LWE) {
                last_snd_data_ack_set(dtcp, LWE);
                if (!a) {
#if 0
                        if (seq > LWE) {
                                LOG_DBG("This is a NACK, "
                                        "LWE couldn't be updated");
                                if (flow_ctrl) {
                                        return PDU_TYPE_NACK_AND_FC;
                                }
                                return PDU_TYPE_NACK;
                        }
#endif
                        LOG_DBG("This is an ACK");
                        if (flow_ctrl) {
                                return PDU_TYPE_ACK_AND_FC;
                        }
                        return PDU_TYPE_ACK;
                }
#if 0
                if (seq > LWE) {
                        /* FIXME: This should be a SEL ACK */
                        LOG_DBG("This is a NACK, "
                                "LWE couldn't be updated");
                        if (flow_ctrl) {
                                return PDU_TYPE_NACK_AND_FC;
                        }
                        return PDU_TYPE_NACK;
                }
#endif
                LOG_DBG("This is an ACK");
                if (flow_ctrl) {
                        return PDU_TYPE_ACK_AND_FC;
                }
                return PDU_TYPE_ACK;
        }

        return 0;
}
Example #29
0
/*
 * As "the server", this ends SET/ACK.
 * As "the client", this ends REQ/REPLY.
 */
static int
cfg_initiator_recv_ATTR(struct message *msg)
{
	struct payload *attrp = payload_first(msg, ISAKMP_PAYLOAD_ATTRIBUTE);
	struct ipsec_exch *ie = msg->exchange->data;
	struct sa      *isakmp_sa = msg->isakmp_sa;
	struct isakmp_cfg_attr *attr;
	struct sockaddr *sa;
	const char     *uk_addr = "<unknown>";
	char           *addr;

	if (msg->exchange->phase == 2)
		if (cfg_verify_hash(msg))
			return -1;

	/* Sanity.  */
	if (ie->cfg_id != GET_ISAKMP_ATTRIBUTE_ID(attrp->p)) {
		log_print("cfg_initiator_recv_ATTR: "
		    "cfg packet ID does not match!");
		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
		return -1;
	}
	switch (attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]) {
	case ISAKMP_CFG_ACK:
		if (ie->cfg_type != ISAKMP_CFG_SET) {
			log_print("cfg_initiator_recv_ATTR: "
			    "bad packet type ACK");
			message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED,
			    0, 1, 0);
			return -1;
		}
		break;
	case ISAKMP_CFG_REPLY:
		if (ie->cfg_type != ISAKMP_CFG_REQUEST) {
			log_print("cfg_initiator_recv_ATTR: "
			    "bad packet type REPLY");
			message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED,
			    0, 1, 0);
			return -1;
		}
		break;

	default:
		log_print("cfg_initiator_recv_ATTR: unexpected configuration "
		    "message type %d", attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]);
		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
		return -1;
	}

	attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF,
	    GET_ISAKMP_GEN_LENGTH(attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
	    cfg_decode_attribute, ie);

	switch (ie->cfg_type) {
	case ISAKMP_CFG_ACK: {
			/* SET/ACK -- Server side (ACK from client) */
			msg->transport->vtbl->get_src(isakmp_sa->transport,
			    &sa);
			if (sockaddr2text(sa, &addr, 0) < 0)
				addr = (char *) uk_addr;

			for (attr = LIST_FIRST(&ie->attrs); attr;
			    attr = LIST_NEXT(attr, link))
				LOG_DBG((LOG_NEGOTIATION, 50,
				    "cfg_initiator_recv_ATTR: "
				    "client %s ACKs attribute %s", addr,
				    constant_name(isakmp_cfg_attr_cst,
					attr->type)));

			if (addr != uk_addr)
				free(addr);
		}
		break;

	case ISAKMP_CFG_REPLY: {
			/*
			 * REQ/REPLY: effect attributes we've gotten
			 * responses on.
			 */
			msg->transport->vtbl->get_src(isakmp_sa->transport,
			    &sa);
			if (sockaddr2text(sa, &addr, 0) < 0)
				addr = (char *) uk_addr;

			for (attr = LIST_FIRST(&ie->attrs); attr;
			    attr = LIST_NEXT(attr, link))
				LOG_DBG((LOG_NEGOTIATION, 50,
				    "cfg_initiator_recv_ATTR: "
				    "server %s replied with attribute %s",
				    addr, constant_name(isakmp_cfg_attr_cst,
					attr->type)));

			if (addr != uk_addr)
				free(addr);
		}
		break;

	default:
		break;
	}

	attrp->flags |= PL_MARK;
	return 0;
}
Example #30
0
static int fxos8700_init(struct device *dev)
{
	const struct fxos8700_config *config = dev->config->config_info;
	struct fxos8700_data *data = dev->driver_data;
	struct sensor_value odr = {.val1 = 6, .val2 = 250000};

	/* Get the I2C device */
	data->i2c = device_get_binding(config->i2c_name);
	if (data->i2c == NULL) {
		LOG_ERR("Could not find I2C device");
		return -EINVAL;
	}

	/*
	 * Read the WHOAMI register to make sure we are talking to FXOS8700 or
	 * compatible device and not some other type of device that happens to
	 * have the same I2C address.
	 */
	if (i2c_reg_read_byte(data->i2c, config->i2c_address,
			      FXOS8700_REG_WHOAMI, &data->whoami)) {
		LOG_ERR("Could not get WHOAMI value");
		return -EIO;
	}

	switch (data->whoami) {
	case WHOAMI_ID_MMA8451:
	case WHOAMI_ID_MMA8652:
	case WHOAMI_ID_MMA8653:
		if (config->mode != FXOS8700_MODE_ACCEL) {
			LOG_ERR("Device 0x%x supports only "
				    "accelerometer mode",
				    data->whoami);
			return -EIO;
		}
	case WHOAMI_ID_FXOS8700:
		LOG_DBG("Device ID 0x%x", data->whoami);
		break;
	default:
		LOG_ERR("Unknown Device ID 0x%x", data->whoami);
		return -EIO;
	}

	/* Reset the sensor. Upon issuing a software reset command over the I2C
	 * interface, the sensor immediately resets and does not send any
	 * acknowledgment (ACK) of the written byte to the master. Therefore,
	 * do not check the return code of the I2C transaction.
	 */
	i2c_reg_write_byte(data->i2c, config->i2c_address,
			   FXOS8700_REG_CTRLREG2, FXOS8700_CTRLREG2_RST_MASK);

	/* The sensor requires us to wait 1 ms after a software reset before
	 * attempting further communications.
	 */
	k_busy_wait(USEC_PER_MSEC);

	if (fxos8700_set_odr(dev, &odr)) {
		LOG_ERR("Could not set default data rate");
		return -EIO;
	}

	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_CTRLREG2,
				FXOS8700_CTRLREG2_MODS_MASK,
				config->power_mode)) {
		LOG_ERR("Could not set power scheme");
		return -EIO;
	}

	/* Set the mode (accel-only, mag-only, or hybrid) */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_M_CTRLREG1,
				FXOS8700_M_CTRLREG1_MODE_MASK,
				config->mode)) {
		LOG_ERR("Could not set mode");
		return -EIO;
	}

	/* Set hybrid autoincrement so we can read accel and mag channels in
	 * one I2C transaction.
	 */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_M_CTRLREG2,
				FXOS8700_M_CTRLREG2_AUTOINC_MASK,
				FXOS8700_M_CTRLREG2_AUTOINC_MASK)) {
		LOG_ERR("Could not set hybrid autoincrement");
		return -EIO;
	}

	/* Set the full-scale range */
	if (i2c_reg_update_byte(data->i2c, config->i2c_address,
				FXOS8700_REG_XYZ_DATA_CFG,
				FXOS8700_XYZ_DATA_CFG_FS_MASK,
				config->range)) {
		LOG_ERR("Could not set range");
		return -EIO;
	}

	k_sem_init(&data->sem, 0, UINT_MAX);

#if CONFIG_FXOS8700_TRIGGER
	if (fxos8700_trigger_init(dev)) {
		LOG_ERR("Could not initialize interrupts");
		return -EIO;
	}
#endif

	/* Set active */
	if (fxos8700_set_power(dev, FXOS8700_POWER_ACTIVE)) {
		LOG_ERR("Could not set active");
		return -EIO;
	}
	k_sem_give(&data->sem);

	LOG_DBG("Init complete");

	return 0;
}

static const struct sensor_driver_api fxos8700_driver_api = {
	.sample_fetch = fxos8700_sample_fetch,
	.channel_get = fxos8700_channel_get,
	.attr_set = fxos8700_attr_set,
#if CONFIG_FXOS8700_TRIGGER
	.trigger_set = fxos8700_trigger_set,
#endif
};

static const struct fxos8700_config fxos8700_config = {
	.i2c_name = CONFIG_FXOS8700_I2C_NAME,
	.i2c_address = CONFIG_FXOS8700_I2C_ADDRESS,
#ifdef CONFIG_FXOS8700_MODE_ACCEL
	.mode = FXOS8700_MODE_ACCEL,
	.start_addr = FXOS8700_REG_OUTXMSB,
	.start_channel = FXOS8700_CHANNEL_ACCEL_X,
	.num_channels = FXOS8700_NUM_ACCEL_CHANNELS,
#elif CONFIG_FXOS8700_MODE_MAGN
	.mode = FXOS8700_MODE_MAGN,
	.start_addr = FXOS8700_REG_M_OUTXMSB,
	.start_channel = FXOS8700_CHANNEL_MAGN_X,
	.num_channels = FXOS8700_NUM_MAG_CHANNELS,
#else
	.mode = FXOS8700_MODE_HYBRID,
	.start_addr = FXOS8700_REG_OUTXMSB,
	.start_channel = FXOS8700_CHANNEL_ACCEL_X,
	.num_channels = FXOS8700_NUM_HYBRID_CHANNELS,
#endif
#if CONFIG_FXOS8700_PM_NORMAL
	.power_mode = FXOS8700_PM_NORMAL,
#elif CONFIG_FXOS8700_PM_LOW_NOISE_LOW_POWER
	.power_mode = FXOS8700_PM_LOW_NOISE_LOW_POWER,
#elif CONFIG_FXOS8700_PM_HIGH_RESOLUTION
	.power_mode = FXOS8700_PM_HIGH_RESOLUTION,
#else
	.power_mode = FXOS8700_PM_LOW_POWER,
#endif
#if CONFIG_FXOS8700_RANGE_8G
	.range = FXOS8700_RANGE_8G,
#elif CONFIG_FXOS8700_RANGE_4G
	.range = FXOS8700_RANGE_4G,
#else
	.range = FXOS8700_RANGE_2G,
#endif
#ifdef CONFIG_FXOS8700_TRIGGER
	.gpio_name = CONFIG_FXOS8700_GPIO_NAME,
	.gpio_pin = CONFIG_FXOS8700_GPIO_PIN,
#endif
#ifdef CONFIG_FXOS8700_PULSE
	.pulse_cfg = CONFIG_FXOS8700_PULSE_CFG,
	.pulse_ths[0] = CONFIG_FXOS8700_PULSE_THSX,
	.pulse_ths[1] = CONFIG_FXOS8700_PULSE_THSY,
	.pulse_ths[2] = CONFIG_FXOS8700_PULSE_THSZ,
	.pulse_tmlt = CONFIG_FXOS8700_PULSE_TMLT,
	.pulse_ltcy = CONFIG_FXOS8700_PULSE_LTCY,
	.pulse_wind = CONFIG_FXOS8700_PULSE_WIND,
#endif
};

static struct fxos8700_data fxos8700_data;

DEVICE_AND_API_INIT(fxos8700, CONFIG_FXOS8700_NAME, fxos8700_init,
		    &fxos8700_data, &fxos8700_config,
		    POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
		    &fxos8700_driver_api);