enum {
        SCARLETT2_FLASH_WRITE_STATE_IDLE = 0,
        SCARLETT2_FLASH_WRITE_STATE_SELECTED = 1,
-       SCARLETT2_FLASH_WRITE_STATE_ERASING = 2
+       SCARLETT2_FLASH_WRITE_STATE_ERASING = 2,
+       SCARLETT2_FLASH_WRITE_STATE_WRITE = 3
 };
 
 static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
 #define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1
 
 #define SCARLETT2_FLASH_BLOCK_SIZE 4096
+#define SCARLETT2_FLASH_WRITE_MAX 1024
 #define SCARLETT2_SEGMENT_NUM_MIN 1
 #define SCARLETT2_SEGMENT_NUM_MAX 4
 
                return -EFAULT;
 
        /* If the erase is complete, change the state from ERASING to
-        * IDLE.
+        * WRITE.
         */
        if (progress.progress == 0xff)
-               private->flash_write_state = SCARLETT2_FLASH_WRITE_STATE_IDLE;
+               private->flash_write_state = SCARLETT2_FLASH_WRITE_STATE_WRITE;
 
        return 0;
 }
        }
 }
 
+static long scarlett2_hwdep_write(struct snd_hwdep *hw,
+                                 const char __user *buf,
+                                 long count, loff_t *offset)
+{
+       struct usb_mixer_interface *mixer = hw->private_data;
+       struct scarlett2_data *private = mixer->private_data;
+       int segment_id, segment_num, err, len;
+       int flash_size;
+
+       /* SCARLETT2_USB_WRITE_SEGMENT request data */
+       struct {
+               __le32 segment_num;
+               __le32 offset;
+               __le32 pad;
+               u8 data[];
+       } __packed *req;
+
+       /* Calculate the maximum permitted in data[] */
+       const size_t max_data_size = SCARLETT2_FLASH_WRITE_MAX -
+                                    offsetof(typeof(*req), data);
+
+       /* If erasing, wait for it to complete */
+       if (private->flash_write_state ==
+             SCARLETT2_FLASH_WRITE_STATE_ERASING) {
+               err = scarlett2_wait_for_erase(mixer);
+               if (err < 0)
+                       return err;
+               private->flash_write_state = SCARLETT2_FLASH_WRITE_STATE_WRITE;
+
+       /* Check that an erase has been done & completed */
+       } else if (private->flash_write_state !=
+                    SCARLETT2_FLASH_WRITE_STATE_WRITE) {
+               return -EINVAL;
+       }
+
+       /* Check that we're writing to the upgrade firmware */
+       segment_id = private->selected_flash_segment_id;
+       if (segment_id != SCARLETT2_SEGMENT_ID_FIRMWARE)
+               return -EINVAL;
+
+       segment_num = private->flash_segment_nums[segment_id];
+       if (segment_num < SCARLETT2_SEGMENT_NUM_MIN ||
+           segment_num > SCARLETT2_SEGMENT_NUM_MAX)
+               return -EFAULT;
+
+       /* Validate the offset and count */
+       flash_size = private->flash_segment_blocks[segment_id] *
+                    SCARLETT2_FLASH_BLOCK_SIZE;
+
+       if (count < 0 || *offset < 0 || *offset + count >= flash_size)
+               return -EINVAL;
+
+       if (!count)
+               return 0;
+
+       /* Limit the *req size to SCARLETT2_FLASH_WRITE_MAX */
+       if (count > max_data_size)
+               count = max_data_size;
+
+       /* Create and send the request */
+       len = struct_size(req, data, count);
+       req = kzalloc(len, GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       req->segment_num = cpu_to_le32(segment_num);
+       req->offset = cpu_to_le32(*offset);
+       req->pad = 0;
+
+       if (copy_from_user(req->data, buf, count)) {
+               err = -EFAULT;
+               goto error;
+       }
+
+       err = scarlett2_usb(mixer, SCARLETT2_USB_WRITE_SEGMENT,
+                           req, len, NULL, 0);
+       if (err < 0)
+               goto error;
+
+       *offset += count;
+       err = count;
+
+error:
+       kfree(req);
+       return err;
+}
+
 static int scarlett2_hwdep_release(struct snd_hwdep *hw, struct file *file)
 {
        struct usb_mixer_interface *mixer = hw->private_data;
        hw->exclusive = 1;
        hw->ops.open = scarlett2_hwdep_open;
        hw->ops.ioctl = scarlett2_hwdep_ioctl;
+       hw->ops.write = scarlett2_hwdep_write;
        hw->ops.release = scarlett2_hwdep_release;
 
        return 0;