示例#1
0
/**
 * read_and_send_file_part() - Transmit a part of the supplied file.
 * @user:	User data for current channel.
 * @logger:	User data for logger channel.
 * @info:	File information.
 *
 * The cg2900_read_and_send_file_part() function transmit a part of the supplied
 * file to the controller.
 *
 * Returns:
 *   0 if there is no more data in the file.
 *   >0 for number of bytes sent.
 *   -ENOMEM if skb allocation failed.
 */
int cg2900_read_and_send_file_part(struct cg2900_user_data *user,
				   struct cg2900_user_data *logger,
				   struct cg2900_file_info *info,
				   const struct firmware *fw_file,
					u8 h4_channel)
{
	int bytes_to_copy;
	struct sk_buff *skb;
	struct bt_vs_write_file_block_cmd *cmd;
	int plen;

	/*
	 * Calculate number of bytes to copy;
	 * either max bytes for HCI packet or number of bytes left in file
	 */
	bytes_to_copy = min((int)HCI_BT_SEND_FILE_MAX_CHUNK_SIZE,
			    (int)(fw_file->size - info->file_offset));

	if (bytes_to_copy <= 0) {
		/* Nothing more to read in file. */
		dev_dbg(user->dev, "File download finished\n");
		info->chunk_id = 0;
		info->file_offset = 0;
		return 0;
	}

	/* There is more data to send */
	plen = sizeof(*cmd) + bytes_to_copy;
	skb = user->alloc_skb(plen, GFP_KERNEL);
	if (!skb) {
		dev_err(user->dev, "Couldn't allocate sk_buffer\n");
		return -ENOMEM;
	}

	skb_put(skb, plen);

	cmd = (struct bt_vs_write_file_block_cmd *)skb->data;
	cmd->opcode = cpu_to_le16(CG2900_BT_OP_VS_WRITE_FILE_BLOCK);
	cmd->plen = BT_PARAM_LEN(plen);
	cmd->id = info->chunk_id;
	info->chunk_id++;

	/* Copy the data from offset position */
	memcpy(cmd->data,
	       &(fw_file->data[info->file_offset]),
	       bytes_to_copy);

	/* Increase offset with number of bytes copied */
	info->file_offset += bytes_to_copy;

	skb_push(skb, CG2900_SKB_RESERVE);
	skb->data[0] = h4_channel;

	cg2900_tx_to_chip(user, logger, skb);

	return bytes_to_copy;
}
/**
 * create_and_send_bt_cmd() - Copy and send sk_buffer.
 * @user:	User data for current channel.
 * @logger:	User data for logger channel.
 * @data:	Data to send.
 * @length:	Length in bytes of data.
 *
 * The create_and_send_bt_cmd() function allocate sk_buffer, copy supplied data
 * to it, and send the sk_buffer to controller.
 */
void cg2900_send_bt_cmd(struct cg2900_user_data *user,
			struct cg2900_user_data *logger,
			void *data, int length)
{
	struct sk_buff *skb;

	skb = user->alloc_skb(length, GFP_ATOMIC);
	if (!skb) {
		dev_err(user->dev, "cg2900_send_bt_cmd: Couldn't alloc "
			"sk_buff with length %d\n", length);
		return;
	}

	memcpy(skb_put(skb, length), data, length);
	skb_push(skb, HCI_H4_SIZE);
	skb->data[0] = HCI_BT_CMD_H4_CHANNEL;

	cg2900_tx_to_chip(user, logger, skb);
}