#include "tascam.h"
 
+static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf,
+                                  long count, loff_t *offset)
+{
+       struct snd_firewire_event_lock_status event = {
+               .type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
+       };
+
+       event.status = (tscm->dev_lock_count > 0);
+       tscm->dev_lock_changed = false;
+       count = min_t(long, count, sizeof(event));
+
+       spin_unlock_irq(&tscm->lock);
+
+       if (copy_to_user(buf, &event, count))
+               return -EFAULT;
+
+       return count;
+}
+
 static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
                       loff_t *offset)
 {
        struct snd_tscm *tscm = hwdep->private_data;
        DEFINE_WAIT(wait);
-       union snd_firewire_event event = {
-               .lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
-       };
 
        spin_lock_irq(&tscm->lock);
 
                spin_lock_irq(&tscm->lock);
        }
 
-       event.lock_status.status = (tscm->dev_lock_count > 0);
-       tscm->dev_lock_changed = false;
-
-       spin_unlock_irq(&tscm->lock);
-
-       count = min_t(long, count, sizeof(event.lock_status));
-
-       if (copy_to_user(buf, &event, count))
-               return -EFAULT;
+       // NOTE: The acquired lock should be released in callee side.
+       if (tscm->dev_lock_changed) {
+               count = tscm_hwdep_read_locked(tscm, buf, count, offset);
+       } else {
+               spin_unlock_irq(&tscm->lock);
+               count = 0;
+       }
 
        return count;
 }