This is just RFC at this stage, I was getting annoyed at the once-per-second
debug message about unsupported command when using f_mass_storage as a CDROM,
so I quickly hacked that up.

I'm not clearing the events per-se, I'm just sending events based on the
state of pending unit attentions, which seems to be enough to please Linux
on the other side, but definitely needs more testing or expert opinions.

If I find some spare cycle in the next few weeks I might add a few more
of the basic MMC commands so we at least support everything Linux throws
at us for a normal read-only CDROM.

Comments ?

Not-Yet-Signed-off-by: Benjamin Herrenschmidt <b...@kernel.crashing.org>
---
 drivers/usb/gadget/function/f_mass_storage.c | 49 +++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_mass_storage.c 
b/drivers/usb/gadget/function/f_mass_storage.c
index 7b13928077c9..d8c83359f470 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -1390,6 +1390,42 @@ static int do_mode_select(struct fsg_common *common, 
struct fsg_buffhd *bh)
        return -EINVAL;
 }
 
+static int do_get_event_status_notification(struct fsg_common *common,
+                                           struct fsg_buffhd *bh)
+{
+       struct fsg_lun  *curlun = common->curlun;
+       u8              *buf = (u8 *) bh->buf;
+       bool            media_class;
+       u8              event;
+       int             size;
+
+       /* We only support media class */
+       media_class = (common->cmnd[4] & 0x10) != 0;
+
+       /* We just mirror the unit attentions */
+       if (curlun->unit_attention_data == SS_NOT_READY_TO_READY_TRANSITION)
+               event = 2; /* New media */
+       else if (curlun->unit_attention_data == SS_MEDIUM_NOT_PRESENT)
+               event = 3;
+       else
+               event = 0;
+
+       /* Fill common header */
+       size = 4;
+       buf[3] = 0x10; /* Support classes: media */
+       if (media_class) {
+               buf[2] = 4; /* Return media event */
+               if (event == 0)
+                       buf[2] |= 0x80; /* No Event Available */
+               size += 8;
+               buf[4] = event;
+               buf[5] = 1; /* Active */
+               buf[6] = buf[7] = 0;
+       } else {
+               buf[2] = 0; /* None of the req. classes supported */
+       }
+       return size;
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -1753,7 +1789,8 @@ static int check_command(struct fsg_common *common, int 
cmnd_size,
         */
        if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
            common->cmnd[0] != INQUIRY &&
-           common->cmnd[0] != REQUEST_SENSE) {
+           common->cmnd[0] != REQUEST_SENSE &&
+           common->cmnd[0] != GET_EVENT_STATUS_NOTIFICATION) {
                curlun->sense_data = curlun->unit_attention_data;
                curlun->unit_attention_data = SS_NO_SENSE;
                return -EINVAL;
@@ -2025,6 +2062,16 @@ static int do_scsi_command(struct fsg_common *common)
                        reply = do_write(common);
                break;
 
+       case GET_EVENT_STATUS_NOTIFICATION:
+               common->data_size_from_cmnd =
+                       get_unaligned_be16(&common->cmnd[7]);
+               reply = check_command(common, 10, DATA_DIR_TO_HOST,
+                                     (1 << 1) | (1 << 4) | (3 << 7) | (1 << 9),
+                                     0, "GET_EVENT_STATUS_NOTIFICATION");
+               if (reply == 0)
+                       reply = do_get_event_status_notification(common, bh);
+               break;
+
        /*
         * Some mandatory commands that we recognize but don't implement.
         * They don't mean much in this setting.  It's left as an exercise



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to