/** * 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); }