예제 #1
0
static ssize_t bcm2079x_dev_write(struct file *filp, const char __user *buf,
				   size_t count, loff_t *offset)
{
	struct bcm2079x_dev *bcm2079x_dev = filp->private_data;
	char tmp[MAX_BUFFER_SIZE];
	int ret;

	if (count > MAX_BUFFER_SIZE) {
		dev_err(&bcm2079x_dev->client->dev, "out of memory\n");
		return -ENOMEM;
	}

	if (copy_from_user(tmp, buf, count)) {
		dev_err(&bcm2079x_dev->client->dev,
			"failed to copy from user space\n");
		return -EFAULT;
	}

	mutex_lock(&bcm2079x_dev->read_mutex);
	/* Write data */

	ret = i2c_master_send(bcm2079x_dev->client, tmp, count);
	if (ret != count) {
#if 0
		if ((bcm2079x_dev->client->flags & I2C_CLIENT_TEN) != I2C_CLIENT_TEN && bcm2079x_dev->error_write == 0) {
			set_client_addr(bcm2079x_dev, 0x1FA);
			ret = i2c_master_send(bcm2079x_dev->client, tmp, count);
            if (ret != count) {
				bcm2079x_dev->error_write++;
                set_client_addr(bcm2079x_dev, bcm2079x_dev->original_address);
            }
		} 
		else
#endif
		{
			dev_err(&bcm2079x_dev->client->dev,
				"failed to write %d\n", ret);
			ret = -EIO;
			bcm2079x_dev->error_write++;
		}
	}
	mutex_unlock(&bcm2079x_dev->read_mutex);
	
	//printk("[dsc]write data ,length =%d \n",ret);
	//print_hex_dump(KERN_DEBUG, " write: ", DUMP_PREFIX_NONE, 16, 1, tmp, ret, false);

	return ret;
}
static long bcm2079x_dev_unlocked_ioctl(struct file *filp,
					 unsigned int cmd, unsigned long arg)
{
	struct bcm2079x_dev *bcm2079x_dev = filp->private_data;

	switch (cmd) {
	case BCMNFC_READ_FULL_PACKET:
		break;
	case BCMNFC_READ_MULTI_PACKETS:
		break;
	case BCMNFC_CHANGE_ADDR:
		dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_CHANGE_ADDR (%x, %lx):\n", __func__, cmd,
			 arg);
		return change_client_addr(bcm2079x_dev, arg);
	case BCMNFC_POWER_CTL:
		gpio_set_value(bcm2079x_dev->en_gpio, arg);
		break;
	case BCMNFC_WAKE_CTL:
		gpio_set_value(bcm2079x_dev->wake_gpio, arg);
		break;
	case BCMNFC_SET_ADDR:
		set_client_addr(bcm2079x_dev, arg);
		break;
	default:
		dev_err(&bcm2079x_dev->client->dev,
			"%s, unknown cmd (%x, %lx)\n", __func__, cmd, arg);
		return 0;
	}

	return 0;
}
예제 #3
0
static ssize_t bcm2079x_dev_write(struct file *filp, const char __user *buf,
				   size_t count, loff_t *offset)
{
	struct bcm2079x_dev *bcm2079x_dev = filp->private_data;
	char tmp[MAX_BUFFER_SIZE];
	int ret;

	DBG2(dev_info(&bcm2079x_dev->client->dev,
		      "bcm2079x_dev_write enter %llu\n", get_jiffies_64()));

	if (count > MAX_BUFFER_SIZE) {
		dev_err(&bcm2079x_dev->client->dev, "out of memory\n");
		return -ENOMEM;
	}

	if (copy_from_user(tmp, buf, count)) {
		dev_err(&bcm2079x_dev->client->dev,
			"failed to copy from user space\n");
		return -EFAULT;
	}

	mutex_lock(&bcm2079x_dev->read_mutex);
	/* Write data */

	ret = i2c_master_send(bcm2079x_dev->client, tmp, count);
	if (ret != count) {
		if ((bcm2079x_dev->client->flags & I2C_CLIENT_TEN) != I2C_CLIENT_TEN && bcm2079x_dev->error_write == 0) {
			set_client_addr(bcm2079x_dev, 0x1FA);
			ret = i2c_master_send(bcm2079x_dev->client, tmp, count);
			if (ret != count) {
				bcm2079x_dev->error_write++;
				set_client_addr(bcm2079x_dev, bcm2079x_dev->original_address);
			}
		} else {
			dev_err(&bcm2079x_dev->client->dev,
				"failed to write %d\n", ret);
			ret = -EIO;
			bcm2079x_dev->error_write++;
		}
	}
	mutex_unlock(&bcm2079x_dev->read_mutex);
	DBG2(dev_info(&bcm2079x_dev->client->dev,
		      "bcm2079x_dev_write leave\n"));

	return ret;
}
예제 #4
0
void redis_command::set_client(redis_client* conn)
{
	if (conn != NULL)
	{
		conn_ = conn;
		cluster_ = NULL;
		set_client_addr(*conn);
	}
}
예제 #5
0
static long bcm2079x_dev_compat_unlocked_ioctl(struct file *filp,
					 unsigned int cmd, unsigned long arg)
{
	struct bcm2079x_dev *bcm2079x_dev = filp->private_data;
	printk("[dsc-test]bcm2079x_dev_compat_unlocked_ioctl\n");
	arg = (compat_u64)arg;
	switch (cmd) {
	case BCMNFC_READ_FULL_PACKET:
		break;
	case BCMNFC_READ_MULTI_PACKETS:
		break;
	case BCMNFC_CHANGE_ADDR:
		dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_CHANGE_ADDR (%x, %lx):\n", __func__, cmd,
			 arg);
		change_client_addr(bcm2079x_dev, arg);
		break;
	case BCMNFC_POWER_CTL:
		dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_POWER_CTL (%x, %lx):\n", __func__, cmd,
			 arg);
		if (arg != 1)
			set_client_addr(bcm2079x_dev, bcm2079x_dev->original_address);
		gpio_set_value(bcm2079x_dev->en_gpio, arg);
		break;
	case BCMNFC_WAKE_CTL:
		dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_WAKE_CTL (%x, %lx):\n", __func__, cmd,
			 arg);
		//printk("zhanglongbo:arg is %lx\n",arg);
#ifdef USE_WAKE_LOCK
		if(arg != 0)
		{
			while(wake_lock_active(&bcm2079x_dev->wake_lock ))
			{
				printk("release wake lock!!!\n");
				wake_unlock(&bcm2079x_dev->wake_lock);
			}
			wake_lock_timeout(&bcm2079x_dev->wake_lock, HZ*2);
		}
#endif
		gpio_set_value(bcm2079x_dev->wake_gpio, arg);
		break;
	default:
		dev_err(&bcm2079x_dev->client->dev,
			"%s, unknown cmd (%x, %lx)\n", __func__, cmd, arg);
		return 0;
	}

	return 0;
}
예제 #6
0
redis_command::redis_command(redis_client* conn)
: check_addr_(false)
, conn_(conn)
, cluster_(NULL)
, max_conns_(0)
, used_(0)
, slot_(-1)
, redirect_max_(15)
, redirect_sleep_(1)
, slice_req_(false)
, request_buf_(NULL)
, request_obj_(NULL)
, argv_size_(0)
, argv_(NULL)
, argv_lens_(NULL)
, slice_res_(false)
, result_(NULL)
{
	dbuf_ = new dbuf_pool();
	if (conn != NULL)
		set_client_addr(*conn);
	else
		addr_[0] = 0;
}
예제 #7
0
const redis_result* redis_command::run(redis_client_cluster* cluster,
	size_t nchild, int* timeout /* = NULL */)
{
	redis_client* conn = peek_conn(cluster, slot_);

	// 如果没有找到可用的连接对象,则直接返回 NULL 表示出错
	if (conn == NULL)
	{
		logger_error("peek_conn NULL, slot_: %d", slot_);
		return NULL;
	}

	set_client_addr(*conn);
	conn->set_check_addr(check_addr_);

	redis_result_t type;
	bool  last_moved = false;
	int   n = 0;

	while (n++ < redirect_max_)
	{
		// 根据请求过程是否采用内存分片方式调用不同的请求过程
		if (slice_req_)
			result_ = conn->run(dbuf_, *request_obj_, nchild, timeout);
		else
			result_ = conn->run(dbuf_, *request_buf_, nchild, timeout);

		// 如果连接异常断开,则需要进行重试
		if (conn->eof())
		{
			// 删除哈希槽中的地址映射关系以便下次操作时重新获取
			cluster->clear_slot(slot_);

			// 将连接对象归还给连接池对象
			conn->get_pool()->put(conn, false);

			// 如果连接断开且请求数据为空时,则无须重试
			if (request_obj_->get_size() == 0 && request_buf_->empty())
			{
				logger_error("not retry when no request!");
				return NULL;
			}

			// 将连接池对象置为不可用状态
			conn->get_pool()->set_alive(false);

			// 从连接池集群中顺序取得一个连接对象
			conn = peek_conn(cluster, slot_);
			if (conn == NULL)
			{
				logger_error("peek_conn NULL");
				return result_;
			}

			last_moved = true;
			clear(true);
			set_client_addr(*conn);
			continue;
		}

		if (result_ == NULL)
		{
			// 将旧连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);
			logger_error("result NULL");

			return NULL;
		}

		// 取得服务器的响应结果的类型,并进行分别处理
		type = result_->get_type();

		if (type == REDIS_RESULT_UNKOWN)
		{
			// 将旧连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);
			logger_error("unknown result type: %d", type);

			return NULL;
		}

		if (type != REDIS_RESULT_ERROR)
		{
			// 如果发生重定向过程,则设置哈希槽对应 redis 服务地址
			if (slot_ < 0 || !last_moved)
			{
				// 将连接对象归还给连接池对象
				conn->get_pool()->put(conn, true);
				return result_;
			}

			// XXX: 因为此处还要引用一次 conn 对象,所以将 conn
			// 归还给连接池的过程须放在此段代码之后
			const char* addr = conn->get_pool()->get_addr();
			cluster->set_slot(slot_, addr);

			// 将连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);

			return result_;
		}

#define	EQ(x, y) !strncasecmp((x), (y), sizeof(y) -1)

		// 对于结果类型为错误类型,则需要进一步判断是否是重定向指令
		const char* ptr = result_->get_error();
		if (ptr == NULL || *ptr == 0)
		{
			// 将旧连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);
			logger_error("result error: null");

			return result_;
		}

		// 如果出错信息为重定向指令,则执行重定向过程
		if (EQ(ptr, "MOVED"))
		{
			// 将旧连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);

			const char* addr = get_addr(ptr);
			if (addr == NULL)
			{
				logger_warn("MOVED invalid, ptr: %s", ptr);
				return result_;
			}

			conn = redirect(cluster, addr);

			if (conn == NULL)
			{
				logger_error("redirect NULL, addr: %s", addr);
				return result_;
			}

			ptr = conn->get_pool()->get_addr();

			set_client_addr(ptr);

			if (n >= 2 && redirect_sleep_ > 0
				&& strcmp(ptr, addr) != 0)
			{
				logger("redirect %d, curr %s, waiting %s ...",
					n, ptr, addr);
				acl_doze(redirect_sleep_);
			}

			last_moved = true;

			// 需要保存哈希槽值
			clear(true);
		}
		else if (EQ(ptr, "ASK"))
		{
			// 将旧连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);

			const char* addr = get_addr(ptr);
			if (addr == NULL)
			{
				logger_warn("ASK invalid, ptr: %s", ptr);
				return result_;
			}

			conn = redirect(cluster, addr);
			if (conn == NULL)
			{
				logger_error("redirect NULL, addr: %s", addr);
				return result_;
			}

			ptr = conn->get_pool()->get_addr();

			set_client_addr(ptr);

			if (n >= 2 && redirect_sleep_ > 0
				&& strcmp(ptr, addr) != 0)
			{
				logger("redirect %d, curr %s, waiting %s ...",
					n, ptr, addr);
				acl_doze(redirect_sleep_);
			}

			result_ = conn->run(dbuf_, "ASKING\r\n", 0);
			if (result_ == NULL)
			{
				logger_error("ASKING's reply null");
				return NULL;
			}

			const char* status = result_->get_status();
			if (status == NULL || strcasecmp(status, "OK") != 0)
			{
				logger_error("ASKING's reply error: %s",
					status ? status : "null");
				return NULL;
			}

			last_moved = false;
			clear(true);
		}

		// 处理一个主结点失效的情形
		else if (EQ(ptr, "CLUSTERDOWN"))
		{
			cluster->clear_slot(slot_);

			if (redirect_sleep_ > 0)
			{
				logger("%s: redirect %d, slot %d, waiting %s ...",
					conn->get_pool()->get_addr(),
					n, slot_, ptr);
				acl_doze(redirect_sleep_);
			}

			// 将旧连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);

			conn = peek_conn(cluster, -1);
			if (conn == NULL)
			{
				logger_error("peek_conn NULL");
				return result_;
			}

			clear(true);
			set_client_addr(*conn);
		}

		// 对于其它错误类型,则直接返回本次得到的响应结果对象
		else
		{
			// 将旧连接对象归还给连接池对象
			conn->get_pool()->put(conn, true);

			logger_error("server error: %s", ptr);
			if (!slice_req_)
				logger_error("request: %s",
					request_buf_->c_str());
			return result_;
		}
	}

	if (conn != NULL)
		conn->get_pool()->put(conn, true);

	logger_warn("too many redirect: %d, max: %d", n, redirect_max_);
	return NULL;
}
예제 #8
0
static long bcm2079x_dev_unlocked_ioctl(struct file *filp,
					 unsigned int cmd, unsigned long arg)
{
	struct bcm2079x_dev *bcm2079x_dev = filp->private_data;

	switch (cmd) {
	case BCMNFC_READ_FULL_PACKET:
		DBG(dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_READ_FULL_PACKET (%x, %lx):\n", __func__,
			 cmd, arg));
		break;
	case BCMNFC_READ_MULTI_PACKETS:
		DBG(dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_READ_MULTI_PACKETS (%x, %lx):\n", __func__,
			 cmd, arg));
		break;
	case BCMNFC_CHANGE_ADDR:
		DBG(dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_CHANGE_ADDR (%x, %lx):\n", __func__, cmd,
			 arg));
		change_client_addr(bcm2079x_dev, arg);
		break;
	case BCMNFC_POWER_CTL:
		DBG(dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_POWER_CTL (%x, %lx):\n", __func__, cmd,
			 arg));
		if (arg == 1) {	/* Power On */

			gpio_set_value(bcm2079x_dev->en_gpio, 1);
			if (bcm2079x_dev->irq_enabled == FALSE) {
				bcm2079x_dev->count_irq = 0;
				enable_irq(bcm2079x_dev->client->irq);
				bcm2079x_dev->irq_enabled = true;
			}
		} else {
			if (bcm2079x_dev->irq_enabled == true) {
				bcm2079x_dev->irq_enabled = FALSE;
				disable_irq_nosync(bcm2079x_dev->client->irq);
				if (bcm2079x_dev->count_irq > 0)
					wake_unlock(&nfc_wake_lock);
				}
			gpio_set_value(bcm2079x_dev->en_gpio, 0);
			set_client_addr(bcm2079x_dev,
				bcm2079x_dev->original_address);
		}
		break;
	case BCMNFC_WAKE_CTL:
		DBG(dev_info(&bcm2079x_dev->client->dev,
			 "%s, BCMNFC_WAKE_CTL (%x, %lx):\n", __func__, cmd,
			 arg));

#ifdef CONFIG_HAS_WAKELOCK
		if (arg == 0) {
			wake_lock(&nfc_wake_lock);
			DBG(dev_info(&bcm2079x_dev->client->dev, "%s: got wake lock", __func__));
		}
#endif

		gpio_set_value(bcm2079x_dev->wake_gpio, arg);

#ifdef CONFIG_HAS_WAKELOCK
		if (arg == 1) {
			wake_unlock(&nfc_wake_lock);
			DBG(dev_info(&bcm2079x_dev->client->dev, "%s: release wake lock, count_irq = %d",
						__func__, bcm2079x_dev->count_irq));
		}
#endif
		break;
	default:
		dev_err(&bcm2079x_dev->client->dev,
			"%s, unknown cmd (%x, %lx)\n", __func__, cmd, arg);
		return 0;
	}

	return 0;
}