[RFC PATCH] usb: gadget: mass_storage: Add GET_EVENT_STATUS_NOTIFICATION

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <benh@xxxxxxxxxxxxxxxxxxx>
---
 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux