You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/04/01 17:20:13 UTC
[incubator-nuttx] branch pr685 updated: Check return from
nxsem_wait_initialize()
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch pr685
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/pr685 by this push:
new 9ff1795 Check return from nxsem_wait_initialize()
9ff1795 is described below
commit 9ff17957600c823dee96a7df96e225d019f0ca4a
Author: Gregory Nutt <gn...@nuttx.org>
AuthorDate: Wed Apr 1 10:13:52 2020 -0600
Check return from nxsem_wait_initialize()
Resolution of Issue 619 will require multiple steps, this part of the first step in that resolution: Every call to nxsem_wait_uninterruptible() must handle the return value from nxsem_wait_uninterruptible properly. This commit is only for rwbuffer.c and those files under drivers/serial, drivers/timers, and drivers/usbdev.
This commit completes that step for all of the files under drivers/. Still remaining: All of the files under arch/.
---
drivers/net/tun.c | 2 +-
drivers/rwbuffer.c | 101 ++++++-
drivers/serial/ptmx.c | 71 ++---
drivers/serial/pty.c | 127 +++++----
drivers/timers/pwm.c | 105 ++++---
drivers/usbdev/usbmsc.c | 177 +++++++-----
drivers/usbdev/usbmsc.h | 58 ++--
drivers/usbdev/usbmsc_scsi.c | 635 ++++++++++++++++++++++++-------------------
8 files changed, 727 insertions(+), 549 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 05c9762..9d198f1 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1260,7 +1260,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct tun_device_s *priv = filep->f_priv;
- ssize_t nread;
+ ssize_t nread = 0;
int ret;
if (priv == NULL)
diff --git a/drivers/rwbuffer.c b/drivers/rwbuffer.c
index a827821..f7b0972 100644
--- a/drivers/rwbuffer.c
+++ b/drivers/rwbuffer.c
@@ -63,9 +63,37 @@
* Name: rwb_semtake
****************************************************************************/
-static void rwb_semtake(FAR sem_t *sem)
+static int rwb_semtake(FAR sem_t *sem)
{
- nxsem_wait_uninterruptible(sem);
+ return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: rwb_forcetake
+ ****************************************************************************/
+
+static int rwb_forcetake(FAR sem_t *sem)
+{
+ int result;
+ int ret = OK;
+
+ do
+ {
+ result = rwb_semtake(sem);
+
+ /* The only expected failure is if the thread is canceled */
+
+ DEBUGASSERT(result == OK || result == -ECANCELED);
+ if (ret == OK && result < 0)
+ {
+ /* Remember the first error */
+
+ ret = result;
+ }
+ }
+ while (result < 0);
+
+ return ret;
}
/****************************************************************************
@@ -166,7 +194,7 @@ static void rwb_wrtimeout(FAR void *arg)
* worker thread.
*/
- rwb_semtake(&rwb->wrsem);
+ rwb_forcetake(&rwb->wrsem);
rwb_wrflush(rwb);
rwb_semgive(&rwb->wrsem);
}
@@ -394,7 +422,11 @@ int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb,
finfo("startblock=%d blockcount=%p\n", startblock, blockcount);
- rwb_semtake(&rwb->wrsem);
+ ret = rwb_semtake(&rwb->wrsem);
+ if (ret < 0)
+ {
+ return ret;
+ }
/* Now there are five cases:
*
@@ -531,7 +563,11 @@ int rwb_invalidate_readahead(FAR struct rwbuffer_s *rwb,
finfo("startblock=%d blockcount=%p\n", startblock, blockcount);
- rwb_semtake(&rwb->rhsem);
+ ret = rwb_semtake(&rwb->rhsem);
+ if (ret < 0)
+ {
+ return ret;
+ }
/* Now there are five cases:
*
@@ -763,9 +799,14 @@ static ssize_t rwb_read_(FAR struct rwbuffer_s *rwb, off_t startblock,
{
size_t remaining;
+ ret = nxsem_wait(&rwb->rhsem);
+ if (ret < 0)
+ {
+ return (ssize_t)ret;
+ }
+
/* Loop until we have read all of the requested blocks */
- rwb_semtake(&rwb->rhsem);
for (remaining = nblocks; remaining > 0; )
{
/* Is there anything in the read-ahead buffer? */
@@ -852,9 +893,14 @@ ssize_t rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock,
if (rwb->wrmaxblocks > 0)
{
+ ret = nxsem_wait(&rwb->wrsem);
+ if (ret < 0)
+ {
+ return (ssize_t)ret;
+ }
+
/* If the write buffer overlaps the block(s) requested */
- rwb_semtake(&rwb->wrsem);
if (rwb_overlap(rwb->wrblockstart, rwb->wrnblocks, startblock,
nblocks))
{
@@ -924,7 +970,12 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
* streaming applications.
*/
- rwb_semtake(&rwb->rhsem);
+ ret = nxsem_wait(&rwb->rhsem);
+ if (ret < 0)
+ {
+ return (ssize_t)ret;
+ }
+
if (rwb_overlap(rwb->rhblockstart, rwb->rhnblocks, startblock,
nblocks))
{
@@ -958,7 +1009,12 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
{
/* First flush the cache */
- rwb_semtake(&rwb->wrsem);
+ ret = nxsem_wait(&rwb->wrsem);
+ if (ret < 0)
+ {
+ return (ssize_t)ret;
+ }
+
rwb_wrflush(rwb);
rwb_semgive(&rwb->wrsem);
@@ -970,7 +1026,12 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
{
/* Buffer the data in the write buffer */
- rwb_semtake(&rwb->wrsem);
+ ret = nxsem_wait(&rwb->wrsem);
+ if (ret < 0)
+ {
+ return (ssize_t)ret;
+ }
+
ret = rwb_writebuffer(rwb, startblock, nblocks, wrbuffer);
rwb_semgive(&rwb->wrsem);
}
@@ -1036,7 +1097,12 @@ int rwb_mediaremoved(FAR struct rwbuffer_s *rwb)
#ifdef CONFIG_DRVR_WRITEBUFFER
if (rwb->wrmaxblocks > 0)
{
- rwb_semtake(&rwb->wrsem);
+ ret = rwb_semtake(&rwb->wrsem);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
rwb_resetwrbuffer(rwb);
rwb_semgive(&rwb->wrsem);
}
@@ -1045,7 +1111,12 @@ int rwb_mediaremoved(FAR struct rwbuffer_s *rwb)
#ifdef CONFIG_DRVR_READAHEAD
if (rwb->rhmaxblocks > 0)
{
- rwb_semtake(&rwb->rhsem);
+ ret = rwb_semtake(&rwb->rhsem);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
rwb_resetrhbuffer(rwb);
rwb_semgive(&rwb->rhsem);
}
@@ -1102,12 +1173,14 @@ int rwb_invalidate(FAR struct rwbuffer_s *rwb,
#ifdef CONFIG_DRVR_WRITEBUFFER
int rwb_flush(FAR struct rwbuffer_s *rwb)
{
- rwb_semtake(&rwb->wrsem);
+ int ret;
+
+ ret = rwb_forcetake(&rwb->wrsem);
rwb_wrcanceltimeout(rwb);
rwb_wrflush(rwb);
rwb_semgive(&rwb->wrsem);
- return OK;
+ return ret;
}
#endif
diff --git a/drivers/serial/ptmx.c b/drivers/serial/ptmx.c
index 16dc180..6abca5c 100644
--- a/drivers/serial/ptmx.c
+++ b/drivers/serial/ptmx.c
@@ -1,35 +1,20 @@
/****************************************************************************
* drivers/serial/ptmx.c
*
- * Copyright (C) 2016-2018 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*
****************************************************************************/
@@ -117,22 +102,6 @@ static struct ptmx_dev_s g_ptmx;
****************************************************************************/
/****************************************************************************
- * Name: ptmx_semtake and ptmx_semgive
- *
- * Description:
- * This is just a wrapper to handle the annoying behavior of semaphore
- * waits that return due to the receipt of a signal.
- *
- ****************************************************************************/
-
-static void ptmx_semtake(void)
-{
- nxsem_wait_uninterruptible(&g_ptmx.px_exclsem);
-}
-
-#define ptmx_semgive() nxsem_post(&g_ptmx.px_exclsem)
-
-/****************************************************************************
* Name: ptmx_minor_allocate
*
* Description:
@@ -204,7 +173,11 @@ static int ptmx_open(FAR struct file *filep)
/* Get exclusive access */
- ptmx_semtake();
+ ret = nxsem_wait(&g_ptmx.px_exclsem);
+ if (ret < 0)
+ {
+ return ret;
+ }
/* Allocate a PTY minor */
@@ -246,7 +219,7 @@ static int ptmx_open(FAR struct file *filep)
/* Return the encoded, master file descriptor */
- ptmx_semgive();
+ nxsem_post(&g_ptmx.px_exclsem);
DEBUGASSERT((unsigned)fd <= OPEN_MAXFD);
return (int)OPEN_SETFD(fd);
@@ -254,7 +227,7 @@ errout_with_minor:
ptmx_minor_free(minor);
errout_with_sem:
- ptmx_semgive();
+ nxsem_post(&g_ptmx.px_exclsem);
return ret;
}
@@ -262,7 +235,8 @@ errout_with_sem:
* Name: ptmx_read
****************************************************************************/
-static ssize_t ptmx_read(FAR struct file *filep, FAR char *buffer, size_t len)
+static ssize_t ptmx_read(FAR struct file *filep,
+ FAR char *buffer, size_t len)
{
return 0; /* Return EOF */
}
@@ -271,7 +245,8 @@ static ssize_t ptmx_read(FAR struct file *filep, FAR char *buffer, size_t len)
* Name: ptmx_write
****************************************************************************/
-static ssize_t ptmx_write(FAR struct file *filep, FAR const char *buffer, size_t len)
+static ssize_t ptmx_write(FAR struct file *filep,
+ FAR const char *buffer, size_t len)
{
return len; /* Say that everything was written */
}
diff --git a/drivers/serial/pty.c b/drivers/serial/pty.c
index 1557b8a..3530b95 100644
--- a/drivers/serial/pty.c
+++ b/drivers/serial/pty.c
@@ -1,35 +1,20 @@
/****************************************************************************
* drivers/serial/pty.c
*
- * Copyright (C) 2016-2018 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*
****************************************************************************/
@@ -168,7 +153,7 @@ struct pty_devpair_s
* Private Function Prototypes
****************************************************************************/
-static void pty_semtake(FAR struct pty_devpair_s *devpair);
+static int pty_semtake(FAR struct pty_devpair_s *devpair);
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static void pty_destroy(FAR struct pty_devpair_s *devpair);
#endif
@@ -219,9 +204,9 @@ static const struct file_operations g_pty_fops =
* Name: pty_semtake
****************************************************************************/
-static void pty_semtake(FAR struct pty_devpair_s *devpair)
+static int pty_semtake(FAR struct pty_devpair_s *devpair)
{
- nxsem_wait_uninterruptible(&devpair->pp_exclsem);
+ return nxsem_wait_uninterruptible(&devpair->pp_exclsem);
}
/****************************************************************************
@@ -309,36 +294,48 @@ static int pty_open(FAR struct file *filep)
{
/* Wait until unlocked. We will also most certainly suspend here. */
- nxsem_wait(&devpair->pp_slavesem);
+ ret = nxsem_wait(&devpair->pp_slavesem);
+ if (ret < 0)
+ {
+ return ret;
+ }
/* Get exclusive access to the device structure. This might also
* cause suspension.
*/
- pty_semtake(devpair);
+ ret = pty_semtake(devpair);
+ if (ret < 0)
+ {
+ return ret;
+ }
/* Check again in case something happened asynchronously while we
* were suspended.
*/
if (devpair->pp_locked)
- {
- /* This cannot suspend because we have the scheduler locked.
- * So pp_locked cannot change asyncrhonously between this test
- * and the redundant test at the top of the loop.
- */
-
- pty_semgive(devpair);
- }
+ {
+ /* This cannot suspend because we have the scheduler locked.
+ * So pp_locked cannot change asyncrhonously between this test
+ * and the redundant test at the top of the loop.
+ */
+
+ pty_semgive(devpair);
+ }
}
sched_unlock();
}
else
{
- /* Master ... Get exclusive access to the device structure */
+ /* Master ... Get exclusive access to the device structure */
- pty_semtake(devpair);
+ ret = pty_semtake(devpair);
+ if (ret < 0)
+ {
+ goto errout_with_sem;
+ }
}
#ifndef CONFIG_PSEUDOTERM_SUSV1
@@ -364,6 +361,7 @@ static int pty_open(FAR struct file *filep)
ret = OK;
}
+errout_with_sem:
pty_semgive(devpair);
return ret;
}
@@ -379,6 +377,7 @@ static int pty_close(FAR struct file *filep)
FAR struct inode *inode;
FAR struct pty_dev_s *dev;
FAR struct pty_devpair_s *devpair;
+ int ret;
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
inode = filep->f_inode;
@@ -388,7 +387,11 @@ static int pty_close(FAR struct file *filep)
/* Get exclusive access */
- pty_semtake(devpair);
+ ret = pty_semtake(devpair);
+ if (ret < 0)
+ {
+ return ret;
+ }
#ifdef CONFIG_PSEUDOTERM_SUSV1
/* Did the (single) master just close its reference? */
@@ -561,6 +564,7 @@ static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
}
/* Perform input processing */
+
/* \n -> \r or \r -> \n translation? */
if (ch == '\n' && (dev->pd_iflag & INLCR) != 0)
@@ -578,7 +582,6 @@ static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
if (ch != '\r' || (dev->pd_iflag & IGNCR) == 0)
{
-
/* Transfer the (possibly translated) character and update the
* count of bytes transferred.
*/
@@ -612,7 +615,8 @@ static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
* Name: pty_write
****************************************************************************/
-static ssize_t pty_write(FAR struct file *filep, FAR const char *buffer, size_t len)
+static ssize_t pty_write(FAR struct file *filep,
+ FAR const char *buffer, size_t len)
{
FAR struct inode *inode;
FAR struct pty_dev_s *dev;
@@ -743,7 +747,11 @@ static int pty_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
/* Get exclusive access */
- pty_semtake(devpair);
+ ret = pty_semtake(devpair);
+ if (ret < 0)
+ {
+ return ret;
+ }
/* Handle IOCTL commands */
@@ -920,7 +928,7 @@ static int pty_poll(FAR struct file *filep, FAR struct pollfd *fds,
FAR struct pty_dev_s *dev;
FAR struct pty_devpair_s *devpair;
FAR struct pty_poll_s *pollp = NULL;
- int ret = -ENOSYS;
+ int ret;
int i;
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
@@ -928,7 +936,13 @@ static int pty_poll(FAR struct file *filep, FAR struct pollfd *fds,
dev = inode->i_private;
devpair = dev->pd_devpair;
- pty_semtake(devpair);
+ ret = pty_semtake(devpair);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ ret = -ENOSYS;
if (setup)
{
@@ -983,6 +997,7 @@ static int pty_poll(FAR struct file *filep, FAR struct pollfd *fds,
goto errout;
}
+
pollp->sink = fds->priv;
}
@@ -1005,6 +1020,7 @@ static int pty_unlink(FAR struct inode *inode)
{
FAR struct pty_dev_s *dev;
FAR struct pty_devpair_s *devpair;
+ int ret;
DEBUGASSERT(inode != NULL && inode->i_private != NULL);
dev = inode->i_private;
@@ -1013,7 +1029,11 @@ static int pty_unlink(FAR struct inode *inode)
/* Get exclusive access */
- pty_semtake(devpair);
+ ret = pty_semtake(devpair);
+ if (ret < 0)
+ {
+ return ret;
+ }
/* Indicate that the driver has been unlinked */
@@ -1033,6 +1053,7 @@ static int pty_unlink(FAR struct inode *inode)
return OK;
}
#endif
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -1230,8 +1251,8 @@ errout_with_pipea:
}
errout_with_devpair:
- nxsem_destroy(&devpair->pp_exclsem);
- nxsem_destroy(&devpair->pp_slavesem);
- kmm_free(devpair);
- return ret;
+ nxsem_destroy(&devpair->pp_exclsem);
+ nxsem_destroy(&devpair->pp_slavesem);
+ kmm_free(devpair);
+ return ret;
}
diff --git a/drivers/timers/pwm.c b/drivers/timers/pwm.c
index 060082f..d7533f1 100644
--- a/drivers/timers/pwm.c
+++ b/drivers/timers/pwm.c
@@ -1,35 +1,20 @@
/****************************************************************************
* drivers/timers/pwm.c
*
- * Copyright (C) 2011-2013, 2016-2017 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*
****************************************************************************/
@@ -68,16 +53,20 @@
struct pwm_upperhalf_s
{
- uint8_t crefs; /* The number of times the device has been opened */
- volatile bool started; /* True: pulsed output is being generated */
+ uint8_t crefs; /* The number of times the device has
+ * been opened */
+ volatile bool started; /* True: pulsed output is being
+ * generated */
#ifdef CONFIG_PWM_PULSECOUNT
- volatile bool waiting; /* True: Caller is waiting for the pulse count to expire */
+ volatile bool waiting; /* True: Caller is waiting for the pulse
+ * count to expire */
#endif
- sem_t exclsem; /* Supports mutual exclusion */
+ sem_t exclsem; /* Supports mutual exclusion */
#ifdef CONFIG_PWM_PULSECOUNT
- sem_t waitsem; /* Used to wait for the pulse count to expire */
+ sem_t waitsem; /* Used to wait for the pulse count to
+ * expire */
#endif
- struct pwm_info_s info; /* Pulsed output characteristics */
+ struct pwm_info_s info; /* Pulsed output characteristics */
FAR struct pwm_lowerhalf_s *dev; /* lower-half state */
};
@@ -336,7 +325,8 @@ static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags)
* We do these things before starting the PWM to avoid race conditions.
*/
- upper->waiting = (upper->info.count > 0) && ((oflags & O_NONBLOCK) == 0);
+ upper->waiting = (upper->info.count > 0) &&
+ ((oflags & O_NONBLOCK) == 0);
upper->started = true;
/* Invoke the bottom half method to start the pulse train */
@@ -360,7 +350,12 @@ static int pwm_start(FAR struct pwm_upperhalf_s *upper, unsigned int oflags)
* clear the waiting flag.
*/
- nxsem_wait_uninterruptible(&upper->waitsem);
+ ret = nxsem_wait_uninterruptible(&upper->waitsem);
+ if (ret < 0)
+ {
+ upper->started = false;
+ upper->waiting = false;
+ }
}
}
else
@@ -440,14 +435,15 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
switch (cmd)
{
- /* PWMIOC_SETCHARACTERISTICS - Set the characteristics of the next pulsed
- * output. This command will neither start nor stop the pulsed output.
- * It will either setup the configuration that will be used when the
- * output is started; or it will change the characteristics of the pulsed
- * output on the fly if the timer is already started.
+ /* PWMIOC_SETCHARACTERISTICS - Set the characteristics of the next
+ * pulsed output. This command will neither start nor stop the
+ * pulsed output. It will either setup the configuration that will
+ * be used when the output is started; or it will change the
+ * characteristics of the pulsed output on the fly if the timer is
+ * already started.
*
- * ioctl argument: A read-only reference to struct pwm_info_s that provides
- * the characteristics of the pulsed output.
+ * ioctl argument: A read-only reference to struct pwm_info_s that
+ * provides the characteristics of the pulsed output.
*/
case PWMIOC_SETCHARACTERISTICS:
@@ -475,8 +471,9 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
- /* PWMIOC_GETCHARACTERISTICS - Get the currently selected characteristics of
- * the pulsed output (independent of whether the output is start or stopped).
+ /* PWMIOC_GETCHARACTERISTICS - Get the currently selected
+ * characteristics of the pulsed output (independent of whether the
+ * output is start or stopped).
*
* ioctl argument: A reference to struct pwm_info_s to receive the
* characteristics of the pulsed output.
@@ -484,7 +481,8 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case PWMIOC_GETCHARACTERISTICS:
{
- FAR struct pwm_info_s *info = (FAR struct pwm_info_s *)((uintptr_t)arg);
+ FAR struct pwm_info_s *info =
+ (FAR struct pwm_info_s *)((uintptr_t)arg);
DEBUGASSERT(info != NULL);
memcpy(info, &upper->info, sizeof(struct pwm_info_s));
@@ -493,8 +491,8 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
- /* PWMIOC_START - Start the pulsed output. The PWMIOC_SETCHARACTERISTICS
- * command must have previously been sent.
+ /* PWMIOC_START - Start the pulsed output. The
+ * PWMIOC_SETCHARACTERISTICS command must have previously been sent.
*
* ioctl argument: None
*/
@@ -569,9 +567,9 @@ static int pwm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
* filesystem. The recommended convention is to name all PWM drivers
* as "/dev/pwm0", "/dev/pwm1", etc. where the driver path differs only
* in the "minor" number at the end of the device name.
- * dev - A pointer to an instance of lower half timer driver. This instance
- * is bound to the PWM driver and must persists as long as the driver
- * persists.
+ * dev - A pointer to an instance of lower half timer driver. This
+ * instance is bound to the PWM driver and must persists as long as the
+ * driver persists.
*
* Returned Value:
* Zero on success; a negated errno value on failure.
@@ -584,7 +582,8 @@ int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev)
/* Allocate the upper-half data structure */
- upper = (FAR struct pwm_upperhalf_s *)kmm_zalloc(sizeof(struct pwm_upperhalf_s));
+ upper = (FAR struct pwm_upperhalf_s *)
+ kmm_zalloc(sizeof(struct pwm_upperhalf_s));
if (!upper)
{
pwmerr("Allocation failed\n");
@@ -597,8 +596,8 @@ int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev)
#ifdef CONFIG_PWM_PULSECOUNT
nxsem_init(&upper->waitsem, 0, 0);
- /* The wait semaphore is used for signaling and, hence, should not have priority
- * inheritance enabled.
+ /* The wait semaphore is used for signaling and, hence, should not have
+ * priority inheritance enabled.
*/
nxsem_setprotocol(&upper->waitsem, SEM_PRIO_NONE);
diff --git a/drivers/usbdev/usbmsc.c b/drivers/usbdev/usbmsc.c
index a8b69a4..a61a8b2 100644
--- a/drivers/usbdev/usbmsc.c
+++ b/drivers/usbdev/usbmsc.c
@@ -1,12 +1,25 @@
/****************************************************************************
* drivers/usbdev/usbmsc.c
+ * Mass storage class device. Bulk-only with SCSI subclass.
*
- * Copyright (C) 2008-2012, 2016-2017 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
*
- * Mass storage class device. Bulk-only with SCSI subclass.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*
- * References:
+ ****************************************************************************/
+
+/* References:
* "Universal Serial Bus Mass Storage Class, Specification Overview,"
* Revision 1.2, USB Implementer's Forum, June 23, 2003.
*
@@ -24,35 +37,7 @@
*
* "SCSI Multimedia Commands - 3 (MMC-3)," American National Standard
* for Information Technology, November 12, 2001
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
+ */
/****************************************************************************
* Included Files
@@ -174,9 +159,6 @@ FAR struct usbmsc_dev_s *g_usbmsc_handoff;
****************************************************************************/
/****************************************************************************
- * Class Driver Support
- ****************************************************************************/
-/****************************************************************************
* Name: usbmsc_ep0incomplete
*
* Description:
@@ -230,7 +212,8 @@ static struct usbdev_req_s *usbmsc_allocreq(FAR struct usbdev_ep_s *ep,
*
****************************************************************************/
-static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req)
+static void usbmsc_freereq(FAR struct usbdev_ep_s *ep,
+ FAR struct usbdev_req_s *req)
{
if (ep != NULL && req != NULL)
{
@@ -238,6 +221,7 @@ static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req)
{
EP_FREEBUFFER(ep, req->buf);
}
+
EP_FREEREQ(ep, req);
}
}
@@ -257,7 +241,8 @@ static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req)
static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
FAR struct usbdev_s *dev)
{
- FAR struct usbmsc_dev_s *priv = ((FAR struct usbmsc_driver_s *)driver)->dev;
+ FAR struct usbmsc_dev_s *priv =
+ ((FAR struct usbmsc_driver_s *)driver)->dev;
FAR struct usbmsc_req_s *reqcontainer;
irqstate_t flags;
int ret = OK;
@@ -416,7 +401,7 @@ static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDINVALIDARGS), 0);
return;
- }
+ }
#endif
/* Extract reference to private data */
@@ -435,7 +420,8 @@ static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
* driver un-initialize logic.
*/
- DEBUGASSERT(priv->thstate == USBMSC_STATE_TERMINATED || priv->thstate == USBMSC_STATE_NOTSTARTED);
+ DEBUGASSERT(priv->thstate == USBMSC_STATE_TERMINATED ||
+ priv->thstate == USBMSC_STATE_NOTSTARTED);
/* Make sure that we are not already unbound */
@@ -550,6 +536,7 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
return -ENODEV;
}
#endif
+
ctrlreq = priv->ctrlreq;
/* Extract the little-endian 16-bit values to host order */
@@ -571,8 +558,9 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
{
case USB_REQ_GETDESCRIPTOR:
{
- /* The value field specifies the descriptor type in the MS byte and the
- * descriptor index in the LS byte (order is little endian)
+ /* The value field specifies the descriptor type in the MS byte
+ * and the descriptor index in the LS byte (order is little
+ * endian)
*/
switch (ctrl->value[1])
@@ -607,9 +595,9 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
case USB_DESC_TYPE_OTHERSPEEDCONFIG:
#endif
- /* If the mass storage device is used in as part of a composite device,
- * then the configuration descriptor is provided by logic in the
- * composite device implementation.
+ /* If the mass storage device is used in as part of a
+ * composite device, then the configuration descriptor is
+ * provided by logic in the composite device implementation.
*/
#ifndef CONFIG_USBMSC_COMPOSITE
@@ -636,14 +624,16 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
/* index == language code. */
ret = usbmsc_mkstrdesc(ctrl->value[0],
- (struct usb_strdesc_s *)ctrlreq->buf);
+ (FAR struct usb_strdesc_s *)
+ ctrlreq->buf);
}
break;
#endif
default:
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETUNKNOWNDESC), value);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETUNKNOWNDESC),
+ value);
}
break;
}
@@ -730,7 +720,8 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
break;
default:
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNSUPPORTEDSTDREQ),
+ ctrl->req);
break;
}
}
@@ -758,7 +749,8 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
if (index != USBMSC_INTERFACEID)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_MSRESETNDX), index);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_MSRESETNDX),
+ index);
ret = -EDOM;
}
else
@@ -788,7 +780,8 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
if (index != USBMSC_INTERFACEID)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETMAXLUNNDX), index);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETMAXLUNNDX),
+ index);
ret = -EDOM;
}
else
@@ -867,7 +860,7 @@ static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DISCONNECTINVALIDARGS), 0);
return;
- }
+ }
#endif
/* Extract reference to private data */
@@ -1289,9 +1282,9 @@ void usbmsc_deferredresponse(FAR struct usbmsc_dev_s *priv, bool failed)
*
****************************************************************************/
-static inline void usbmsc_sync_wait(FAR struct usbmsc_dev_s *priv)
+static int usbmsc_sync_wait(FAR struct usbmsc_dev_s *priv)
{
- nxsem_wait_uninterruptible(&priv->thsynch);
+ return nxsem_wait_uninterruptible(&priv->thsynch);
}
/****************************************************************************
@@ -1336,7 +1329,8 @@ int usbmsc_configure(unsigned int nluns, void **handle)
/* Allocate the structures needed */
- alloc = (FAR struct usbmsc_alloc_s *)kmm_malloc(sizeof(struct usbmsc_alloc_s));
+ alloc = (FAR struct usbmsc_alloc_s *)
+ kmm_malloc(sizeof(struct usbmsc_alloc_s));
if (!alloc)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCDEVSTRUCT), 0);
@@ -1390,15 +1384,17 @@ int usbmsc_configure(unsigned int nluns, void **handle)
/* Initialize the device information if we are not part of a composite.
* If we are part of a composite, the device information will be
- * initialized through coordinated actions of usbmsc_get_composite_devdesc()
- * and board-specific logic.
+ * initialized through coordinated actions of
+ * usbmsc_get_composite_devdesc() and board-specific logic.
*/
#ifndef CONFIG_USBMSC_COMPOSITE
/* minor - not used */
+
/* Interfaces (ifnobase == 0) */
- priv->devinfo.ninterfaces = USBMSC_NINTERFACES; /* Number of interfaces in the configuration */
+ priv->devinfo.ninterfaces = USBMSC_NINTERFACES; /* Number of interfaces
+ * in the configuration */
/* Strings (strbase == 0) */
@@ -1428,7 +1424,8 @@ errout:
* Bind the block driver specified by drvrpath to a USB storage LUN.
*
* Input Parameters:
- * handle - The handle returned by a previous call to usbmsc_configure().
+ * handle - The handle returned by a previous call to
+ * usbmsc_configure().
* drvrpath - the full path to the block driver
* startsector - A sector offset into the block driver to the start of the
* partition on drvrpath (0 if no partitions)
@@ -1536,7 +1533,8 @@ int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath,
priv->iobuffer = (FAR uint8_t *)kmm_malloc(geo.geo_sectorsize);
if (!priv->iobuffer)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCIOBUFFER), geo.geo_sectorsize);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCIOBUFFER),
+ geo.geo_sectorsize);
return -ENOMEM;
}
@@ -1549,7 +1547,8 @@ int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath,
tmp = (FAR void *)kmm_realloc(priv->iobuffer, geo.geo_sectorsize);
if (!tmp)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REALLOCIOBUFFER), geo.geo_sectorsize);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REALLOCIOBUFFER),
+ geo.geo_sectorsize);
return -ENOMEM;
}
@@ -1620,7 +1619,11 @@ int usbmsc_unbindlun(FAR void *handle, unsigned int lunno)
#endif
lun = &priv->luntab[lunno];
- usbmsc_scsi_lock(priv);
+ ret = usbmsc_scsi_lock(priv);
+ if (ret < 0)
+ {
+ return ret;
+ }
#ifdef CONFIG_DEBUG_FEATURES
if (lun->inode == NULL)
@@ -1630,12 +1633,12 @@ int usbmsc_unbindlun(FAR void *handle, unsigned int lunno)
}
else
#endif
- {
+ {
/* Close the block driver */
- usbmsc_lununinitialize(lun);
- ret = OK;
- }
+ usbmsc_lununinitialize(lun);
+ ret = OK;
+ }
usbmsc_scsi_unlock(priv);
return ret;
@@ -1667,7 +1670,7 @@ int usbmsc_exportluns(FAR void *handle)
FAR struct usbmsc_driver_s *drvr;
#endif
irqstate_t flags;
- int ret = OK;
+ int ret;
#ifdef CONFIG_DEBUG_FEATURES
if (!alloc)
@@ -1688,7 +1691,11 @@ int usbmsc_exportluns(FAR void *handle)
* some protection against re-entrant usage.
*/
- usbmsc_scsi_lock(priv);
+ ret = usbmsc_scsi_lock(priv);
+ if (ret < 0)
+ {
+ return ret;
+ }
priv->thstate = USBMSC_STATE_NOTSTARTED;
priv->theventset = USBMSC_EVENT_NOEVENTS;
@@ -1709,7 +1716,12 @@ int usbmsc_exportluns(FAR void *handle)
/* Wait for the worker thread to run and initialize */
uinfo("Waiting for the SCSI worker thread\n");
- usbmsc_sync_wait(priv);
+ ret = usbmsc_sync_wait(priv);
+ if (ret < 0)
+ {
+ goto errout_with_lock;
+ }
+
DEBUGASSERT(g_usbmsc_handoff == NULL);
/* Register the USB storage class driver (unless we are part of a composite device) */
@@ -1800,6 +1812,7 @@ void usbmsc_uninitialize(FAR void *handle)
FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
FAR struct usbmsc_dev_s *priv;
irqstate_t flags;
+ int ret;
int i;
#ifdef CONFIG_DEBUG_FEATURES
@@ -1832,9 +1845,23 @@ void usbmsc_uninitialize(FAR void *handle)
if (priv->thstate != USBMSC_STATE_NOTSTARTED)
{
- /* The thread was started.. Is it still running? */
+ /* Get exclusive access to SCSI state data */
+
+ do
+ {
+ ret = usbmsc_scsi_lock(priv);
+
+ /* usbmsc_scsi_lock() will fail with ECANCELED, only
+ * if this thread is canceled. At this point, we
+ * have no option but to continue with the teardown.
+ */
+
+ DEBUGASSERT(ret == OK || ret == -ECANCLED);
+ }
+ while (ret < 0);
+
+ /* The thread was started.. Is it still running? */
- usbmsc_scsi_lock(priv);
if (priv->thstate != USBMSC_STATE_TERMINATED)
{
/* Yes.. Ask the thread to stop */
@@ -1851,7 +1878,15 @@ void usbmsc_uninitialize(FAR void *handle)
while ((priv->theventset & USBMSC_EVENT_TERMINATEREQUEST) != 0)
{
- usbmsc_sync_wait(priv);
+ ret = usbmsc_sync_wait(priv);
+ if (ret < 0)
+ {
+ /* Just break out and continue if the thread has been
+ * canceled.
+ */
+
+ break;
+ }
}
}
diff --git a/drivers/usbdev/usbmsc.h b/drivers/usbdev/usbmsc.h
index 8924e6c..d0f5658 100644
--- a/drivers/usbdev/usbmsc.h
+++ b/drivers/usbdev/usbmsc.h
@@ -1,37 +1,21 @@
/****************************************************************************
* drivers/usbdev/usbmsc.h
+ * Mass storage class device. Bulk-only with SCSI subclass.
*
- * Copyright (C) 2008-2013, 2015, 2017 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
*
- * Mass storage class device. Bulk-only with SCSI subclass.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*
****************************************************************************/
@@ -425,7 +409,7 @@ struct usbmsc_dev_s
struct usbmsc_lun_s *lun; /* Currently selected LUN */
struct usbmsc_lun_s *luntab; /* Allocated table of all LUNs */
- uint8_t cdb[USBMSC_MAXCDBLEN]; /* Command data (cdb[]) from CBW */
+ uint8_t cdb[USBMSC_MAXCDBLEN]; /* Command data (cdb[]) from CBW */
uint8_t phaseerror:1; /* Need to send phase sensing status */
uint8_t shortpacket:1; /* Host transmission stopped unexpectedly */
uint8_t cbwdir:2; /* Direction from CBW. See USBMSC_FLAGS_DIR* definitions */
@@ -483,8 +467,8 @@ EXTERN const char g_mscvendorstr[];
EXTERN const char g_mscproductstr[];
EXTERN const char g_mscserialstr[];
-/* If we are using a composite device, then vendor/product/serial number strings
- * are provided by the composite device logic.
+/* If we are using a composite device, then vendor/product/serial number
+ * strings are provided by the composite device logic.
*/
#else
@@ -513,7 +497,7 @@ EXTERN FAR struct usbmsc_dev_s *g_usbmsc_handoff;
*
****************************************************************************/
-void usbmsc_scsi_lock(FAR struct usbmsc_dev_s *priv);
+int usbmsc_scsi_lock(FAR struct usbmsc_dev_s *priv);
/****************************************************************************
* Name: usbmsc_scsi_unlock
@@ -525,7 +509,7 @@ void usbmsc_scsi_lock(FAR struct usbmsc_dev_s *priv);
#define usbmsc_scsi_unlock(priv) nxsem_post(&priv->thlock)
-/*****************************************************************************
+/****************************************************************************
* Name: usbmsc_scsi_signal
*
* Description:
@@ -591,10 +575,12 @@ int usbmsc_copy_epdesc(enum usbmsc_epdesc_e epid,
****************************************************************************/
#ifdef CONFIG_USBDEV_DUALSPEED
-int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf, FAR struct usbdev_devinfo_s *devinfo,
+int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf,
+ FAR struct usbdev_devinfo_s *devinfo,
uint8_t speed, uint8_t type);
#else
-int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf, FAR struct usbdev_devinfo_s *devinfo);
+int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf,
+ FAR struct usbdev_devinfo_s *devinfo);
#endif
/****************************************************************************
diff --git a/drivers/usbdev/usbmsc_scsi.c b/drivers/usbdev/usbmsc_scsi.c
index 8e99919..3e7620a 100644
--- a/drivers/usbdev/usbmsc_scsi.c
+++ b/drivers/usbdev/usbmsc_scsi.c
@@ -1,13 +1,25 @@
/****************************************************************************
* drivers/usbdev/usbmsc_scsi.c
+ * Mass storage class device. Bulk-only with SCSI subclass.
*
- * Copyright (C) 2008-2010, 2012, 2016-2017, 2019 Gregory Nutt. All rights
- * reserved.
- * Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
*
- * Mass storage class device. Bulk-only with SCSI subclass.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*
- * References:
+ ****************************************************************************/
+
+/* References:
* "Universal Serial Bus Mass Storage Class, Specification Overview,"
* Revision 1.2, USB Implementer's Forum, June 23, 2003.
*
@@ -22,35 +34,7 @@
*
* "SCSI Block Commands -2 (SBC-2)," American National Standard
* for Information Technology, November 13, 2004
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
+ */
/****************************************************************************
* Included Files
@@ -155,7 +139,8 @@ static int usbmsc_modepage(FAR struct usbmsc_dev_s *priv,
static inline int usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv,
FAR uint8_t *buf);
static inline int usbmsc_cmdstartstopunit(FAR struct usbmsc_dev_s *priv);
-static inline int usbmsc_cmdpreventmediumremoval(FAR struct usbmsc_dev_s *priv);
+static inline int usbmsc_cmdpreventmediumremoval(
+ FAR struct usbmsc_dev_s *priv);
static inline int usbmsc_cmdreadformatcapacity(FAR struct usbmsc_dev_s *priv,
FAR uint8_t *buf);
static inline int usbmsc_cmdreadcapacity10(FAR struct usbmsc_dev_s *priv,
@@ -163,7 +148,8 @@ static inline int usbmsc_cmdreadcapacity10(FAR struct usbmsc_dev_s *priv,
static inline int usbmsc_cmdread10(FAR struct usbmsc_dev_s *priv);
static inline int usbmsc_cmdwrite10(FAR struct usbmsc_dev_s *priv);
static inline int usbmsc_cmdverify10(FAR struct usbmsc_dev_s *priv);
-static inline int usbmsc_cmdsynchronizecache10(FAR struct usbmsc_dev_s *priv);
+static inline int usbmsc_cmdsynchronizecache10(
+ FAR struct usbmsc_dev_s *priv);
static inline int usbmsc_cmdmodeselect10(FAR struct usbmsc_dev_s *priv);
static inline int usbmsc_cmdmodesense10(FAR struct usbmsc_dev_s *priv,
FAR uint8_t *buf);
@@ -366,9 +352,11 @@ static void usbmsc_putle32(uint8_t *buf, uint32_t val)
*
****************************************************************************/
-static void usbmsc_scsi_wait(FAR struct usbmsc_dev_s *priv)
+static int usbmsc_scsi_wait(FAR struct usbmsc_dev_s *priv)
{
irqstate_t flags;
+ int ret;
+ int ret2;
/* We must hold the SCSI lock to call this function */
@@ -388,18 +376,19 @@ static void usbmsc_scsi_wait(FAR struct usbmsc_dev_s *priv)
usbmsc_scsi_unlock(priv);
- /* Now wait for a SCSI event to be signalled */
+ /* Now wait for a SCSI event to be signaled */
do
{
- nxsem_wait_uninterruptible(&priv->thwaitsem);
+ ret = nxsem_wait_uninterruptible(&priv->thwaitsem);
}
- while (priv->thwaiting);
+ while (priv->thwaiting && ret >= 0);
/* Re-acquire our lock on the SCSI state data */
- usbmsc_scsi_lock(priv);
+ ret2 = usbmsc_scsi_lock(priv);
leave_critical_section(flags);
+ return ret >= 0 ? ret2 : ret;
}
/****************************************************************************
@@ -457,8 +446,10 @@ static inline int usbmsc_cmdrequestsense(FAR struct usbmsc_dev_s *priv,
}
ret = usbmsc_setupcmd(priv, cdblen,
- USBMSC_FLAGS_DIRDEVICE2HOST | USBMSC_FLAGS_LUNNOTNEEDED |
- USBMSC_FLAGS_UACOKAY | USBMSC_FLAGS_RETAINSENSEDATA);
+ USBMSC_FLAGS_DIRDEVICE2HOST |
+ USBMSC_FLAGS_LUNNOTNEEDED |
+ USBMSC_FLAGS_UACOKAY |
+ USBMSC_FLAGS_RETAINSENSEDATA);
if (ret == OK)
{
lun = priv->lun;
@@ -509,7 +500,8 @@ static inline int usbmsc_cmdrequestsense(FAR struct usbmsc_dev_s *priv,
static inline int usbmsc_cmdread6(FAR struct usbmsc_dev_s *priv)
{
- FAR struct scsicmd_read6_s *read6 = (FAR struct scsicmd_read6_s *)priv->cdb;
+ FAR struct scsicmd_read6_s *read6 =
+ (FAR struct scsicmd_read6_s *)priv->cdb;
FAR struct usbmsc_lun_s *lun;
int ret;
@@ -527,8 +519,9 @@ static inline int usbmsc_cmdread6(FAR struct usbmsc_dev_s *priv)
/* Get the Logical Block Address (LBA) from cdb[] as the starting sector */
- priv->sector = (uint32_t)(read6->mslba & SCSICMD_READ6_MSLBAMASK) << 16 |
- (uint32_t)usbmsc_getbe16(read6->lslba);
+ priv->sector =
+ (uint32_t)(read6->mslba & SCSICMD_READ6_MSLBAMASK) << 16 |
+ (uint32_t)usbmsc_getbe16(read6->lslba);
/* Verify that a block driver has been bound to the LUN */
@@ -571,7 +564,8 @@ static inline int usbmsc_cmdread6(FAR struct usbmsc_dev_s *priv)
static inline int usbmsc_cmdwrite6(FAR struct usbmsc_dev_s *priv)
{
- FAR struct scsicmd_write6_s *write6 = (FAR struct scsicmd_write6_s *)priv->cdb;
+ FAR struct scsicmd_write6_s *write6 =
+ (FAR struct scsicmd_write6_s *)priv->cdb;
FAR struct usbmsc_lun_s *lun;
int ret;
@@ -589,8 +583,9 @@ static inline int usbmsc_cmdwrite6(FAR struct usbmsc_dev_s *priv)
/* Get the Logical Block Address (LBA) from cdb[] as the starting sector */
- priv->sector = (uint32_t)(write6->mslba & SCSICMD_WRITE6_MSLBAMASK) << 16 |
- (uint32_t)usbmsc_getbe16(write6->lslba);
+ priv->sector =
+ (uint32_t)(write6->mslba & SCSICMD_WRITE6_MSLBAMASK) << 16 |
+ (uint32_t)usbmsc_getbe16(write6->lslba);
/* Verify that a block driver has been bound to the LUN */
@@ -643,14 +638,17 @@ static inline int usbmsc_cmdwrite6(FAR struct usbmsc_dev_s *priv)
static inline int usbmsc_cmdinquiry(FAR struct usbmsc_dev_s *priv,
FAR uint8_t *buf)
{
- FAR struct scscicmd_inquiry_s *inquiry = (FAR struct scscicmd_inquiry_s *)priv->cdb;
- FAR struct scsiresp_inquiry_s *response = (FAR struct scsiresp_inquiry_s *)buf;
+ FAR struct scscicmd_inquiry_s *inquiry =
+ (FAR struct scscicmd_inquiry_s *)priv->cdb;
+ FAR struct scsiresp_inquiry_s *response =
+ (FAR struct scsiresp_inquiry_s *)buf;
int len;
int ret;
priv->u.alloclen = usbmsc_getbe16(inquiry->alloclen);
ret = usbmsc_setupcmd(priv, SCSICMD_INQUIRY_SIZEOF,
- USBMSC_FLAGS_DIRDEVICE2HOST | USBMSC_FLAGS_LUNNOTNEEDED |
+ USBMSC_FLAGS_DIRDEVICE2HOST |
+ USBMSC_FLAGS_LUNNOTNEEDED |
USBMSC_FLAGS_UACOKAY);
if (ret == OK)
{
@@ -769,14 +767,24 @@ static int usbmsc_modepage(FAR struct usbmsc_dev_s *priv, FAR uint8_t *buf,
/* None of the fields are changeable */
- if (((pcpgcode & SCSICMD_MODESENSE_PCMASK) != SCSICMD_MODESENSE_PCCHANGEABLE))
+ if (((pcpgcode & SCSICMD_MODESENSE_PCMASK) !=
+ SCSICMD_MODESENSE_PCCHANGEABLE))
{
cmp->flags1 = SCSIRESP_CACHINGMODEPG_WCE; /* Write cache enable */
- cmp->dpflen[0] = 0xff; /* Disable prefetch transfer length = 0xffffffff */
+
+ /* Disable prefetch transfer length = 0xffffffff */
+
+ cmp->dpflen[0] = 0xff;
cmp->dpflen[1] = 0xff;
- cmp->maxpf[0] = 0xff; /* Maximum pre-fetch = 0xffffffff */
+
+ /* Maximum pre-fetch = 0xffffffff */
+
+ cmp->maxpf[0] = 0xff;
cmp->maxpf[1] = 0xff;
- cmp->maxpfc[0] = 0xff; /* Maximum pref-fetch ceiling = 0xffffffff */
+
+ /* Maximum pref-fetch ceiling = 0xffffffff */
+
+ cmp->maxpfc[0] = 0xff;
cmp->maxpfc[1] = 0xff;
}
@@ -833,19 +841,23 @@ static int inline usbmsc_cmdmodesense6(FAR struct usbmsc_dev_s *priv,
*/
mph->type = 0; /* Medium type */
- mph->param = (priv->lun->readonly ? SCSIRESP_MODEPARMHDR_DAPARM_WP : 0x00);
+ mph->param =
+ (priv->lun->readonly ? SCSIRESP_MODEPARMHDR_DAPARM_WP : 0x00);
mph->bdlen = 0; /* Block descriptor length */
/* There are no block descriptors, only the following mode page: */
- ret = usbmsc_modepage(priv, &buf[SCSIRESP_MODEPARAMETERHDR6_SIZEOF],
+ ret = usbmsc_modepage(priv,
+ &buf[SCSIRESP_MODEPARAMETERHDR6_SIZEOF],
modesense->pcpgcode, &mdlen);
if (ret == OK)
{
/* Store the mode data length and return the total message size */
- mph->mdlen = mdlen + SCSIRESP_MODEPARAMETERHDR6_SIZEOF - 1;
- priv->nreqbytes = mdlen + SCSIRESP_MODEPARAMETERHDR6_SIZEOF;
+ mph->mdlen =
+ mdlen + SCSIRESP_MODEPARAMETERHDR6_SIZEOF - 1;
+ priv->nreqbytes =
+ mdlen + SCSIRESP_MODEPARAMETERHDR6_SIZEOF;
}
}
}
@@ -892,7 +904,8 @@ static inline int usbmsc_cmdstartstopunit(FAR struct usbmsc_dev_s *priv)
*
****************************************************************************/
-static inline int usbmsc_cmdpreventmediumremoval(FAR struct usbmsc_dev_s *priv)
+static inline int
+ usbmsc_cmdpreventmediumremoval(FAR struct usbmsc_dev_s *priv)
{
#ifdef CONFIG_USBMSC_REMOVABLE
FAR struct scsicmd_preventmediumremoval_s *pmr =
@@ -914,7 +927,10 @@ static inline int usbmsc_cmdpreventmediumremoval(FAR struct usbmsc_dev_s *priv)
#else
if ((pmr->prevent & ~SCSICMD_PREVENTMEDIUMREMOVAL_TRANSPORT) != 0)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_PREVENTMEDIUMREMOVALPREVENT), 0);
+ usbtrace(
+ TRACE_CLSERROR(USBMSC_TRACEERR_PREVENTMEDIUMREMOVALPREVENT),
+ 0);
+
lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA;
ret = -EINVAL;
}
@@ -1039,7 +1055,8 @@ static inline int usbmsc_cmdread10(FAR struct usbmsc_dev_s *priv)
/* Verify that we can support this read command */
- if ((read10->flags & ~(SCSICMD_READ10FLAGS_DPO | SCSICMD_READ10FLAGS_FUA)) != 0)
+ if ((read10->flags & ~(SCSICMD_READ10FLAGS_DPO |
+ SCSICMD_READ10FLAGS_FUA)) != 0)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ10FLAGS), 0);
lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA;
@@ -1116,7 +1133,8 @@ static inline int usbmsc_cmdwrite10(FAR struct usbmsc_dev_s *priv)
else if (!lun->inode)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE10MEDIANOTPRESENT), 0);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE10MEDIANOTPRESENT),
+ 0);
lun->sd = SCSI_KCQNR_MEDIANOTPRESENT;
ret = -EINVAL;
}
@@ -1162,7 +1180,8 @@ static inline int usbmsc_cmdwrite10(FAR struct usbmsc_dev_s *priv)
static inline int usbmsc_cmdverify10(FAR struct usbmsc_dev_s *priv)
{
- FAR struct scsicmd_verify10_s *verf = (FAR struct scsicmd_verify10_s *)priv->cdb;
+ FAR struct scsicmd_verify10_s *verf =
+ (FAR struct scsicmd_verify10_s *)priv->cdb;
FAR struct usbmsc_lun_s *lun;
uint32_t lba;
uint16_t blocks;
@@ -1198,7 +1217,8 @@ static inline int usbmsc_cmdverify10(FAR struct usbmsc_dev_s *priv)
else if (!lun->inode)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10MEDIANOTPRESENT), 0);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10MEDIANOTPRESENT),
+ 0);
lun->sd = SCSI_KCQNR_MEDIANOTPRESENT;
ret = -EINVAL;
}
@@ -1215,12 +1235,15 @@ static inline int usbmsc_cmdverify10(FAR struct usbmsc_dev_s *priv)
{
/* Try to read the requested blocks */
- for (i = 0, sector = lba + lun->startsector; i < blocks; i++, sector++)
+ for (i = 0, sector = lba + lun->startsector;
+ i < blocks;
+ i++, sector++)
{
nread = USBMSC_DRVR_READ(lun, priv->iobuffer, sector, 1);
if (nread < 0)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10READFAIL), i);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_VERIFY10READFAIL),
+ i);
lun->sd = SCSI_KCQME_UNRRE1;
lun->sdinfo = sector;
ret = -EIO;
@@ -1327,11 +1350,13 @@ static int inline usbmsc_cmdmodesense10(FAR struct usbmsc_dev_s *priv,
*/
memset(mph, 0, SCSIRESP_MODEPARAMETERHDR10_SIZEOF);
- mph->param = (priv->lun->readonly ? SCSIRESP_MODEPARMHDR_DAPARM_WP : 0x00);
+ mph->param =
+ (priv->lun->readonly ? SCSIRESP_MODEPARMHDR_DAPARM_WP : 0x00);
/* There are no block descriptors, only the following mode page: */
- ret = usbmsc_modepage(priv, &buf[SCSIRESP_MODEPARAMETERHDR10_SIZEOF],
+ ret = usbmsc_modepage(priv,
+ &buf[SCSIRESP_MODEPARAMETERHDR10_SIZEOF],
modesense->pcpgcode, &mdlen);
if (ret == OK)
{
@@ -1373,7 +1398,8 @@ static inline int usbmsc_cmdread12(FAR struct usbmsc_dev_s *priv)
/* Verify that we can support this read command */
- if ((read12->flags & ~(SCSICMD_READ12FLAGS_DPO | SCSICMD_READ12FLAGS_FUA)) != 0)
+ if ((read12->flags & ~(SCSICMD_READ12FLAGS_DPO |
+ SCSICMD_READ12FLAGS_FUA)) != 0)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_READ12FLAGS), 0);
lun->sd = SCSI_KCQIR_INVALIDFIELDINCBA;
@@ -1449,7 +1475,8 @@ static inline int usbmsc_cmdwrite12(FAR struct usbmsc_dev_s *priv)
else if (!lun->inode)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE12MEDIANOTPRESENT), 0);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRITE12MEDIANOTPRESENT),
+ 0);
lun->sd = SCSI_KCQNR_MEDIANOTPRESENT;
ret = -EINVAL;
}
@@ -1626,11 +1653,13 @@ static int inline usbmsc_setupcmd(FAR struct usbmsc_dev_s *priv,
* commands is permitted.
*/
- if (lun->uad != SCSI_KCQ_NOSENSE && (flags & USBMSC_FLAGS_UACOKAY) != 0)
+ if (lun->uad != SCSI_KCQ_NOSENSE &&
+ (flags & USBMSC_FLAGS_UACOKAY) != 0)
{
/* Command not permitted */
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDUNEVIOLATION), priv->cbwlun);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDUNEVIOLATION),
+ priv->cbwlun);
lun->sd = lun->uad;
lun->uad = SCSI_KCQ_NOSENSE;
ret = -EINVAL;
@@ -1663,9 +1692,9 @@ static int inline usbmsc_setupcmd(FAR struct usbmsc_dev_s *priv,
* for the receipt of a bulk CBW.
*
* Returned Value:
- * If no new, valid CBW is available, this function returns a negated errno.
- * Otherwise, when a new CBW is successfully parsed, this function sets
- * priv->thstate to USBMSC_STATE_CMDPARSE and returns OK.
+ * If no new, valid CBW is available, this function returns a negated
+ * errno value. Otherwise, when a new CBW is successfully parsed, this
+ * function sets priv->thstate to USBMSC_STATE_CMDPARSE and returns OK.
*
****************************************************************************/
@@ -1712,8 +1741,8 @@ static int usbmsc_idlestate(FAR struct usbmsc_dev_s *priv)
cbw->signature[2] != 'B' ||
cbw->signature[3] != 'C')
{
- /* CBS BAD: Stall the bulk endpoints. If the CBW is bad we must stall the
- * bulk IN endpoint and either (1) stall the bulk OUT endpoint, or
+ /* CBS BAD: Stall the bulk endpoints. If the CBW is bad we must stall
+ * the bulk IN endpoint and either (1) stall the bulk OUT endpoint, or
* (2) discard data from the endpoint.
*/
@@ -1724,11 +1753,13 @@ static int usbmsc_idlestate(FAR struct usbmsc_dev_s *priv)
/* Is the CBW meaningful? */
- else if (cbw->lun >= priv->nluns || (cbw->flags & ~USBMSC_CBWFLAG_IN) != 0 ||
- cbw->cdblen < 6 || cbw->cdblen > USBMSC_MAXCDBLEN)
+ else if (cbw->lun >= priv->nluns ||
+ (cbw->flags & ~USBMSC_CBWFLAG_IN) != 0 ||
+ cbw->cdblen < 6 ||
+ cbw->cdblen > USBMSC_MAXCDBLEN)
{
- /* CBS BAD: Stall the bulk endpoints. If the CBW is bad we must stall the
- * bulk IN endpoint and either (1) stall the bulk OUT endpoint, or
+ /* CBS BAD: Stall the bulk endpoints. If the CBW is bad we must stall
+ * the bulk IN endpoint and either (1) stall the bulk OUT endpoint, or
* (2) discard data from the endpoint.
*/
@@ -1785,7 +1816,8 @@ static int usbmsc_idlestate(FAR struct usbmsc_dev_s *priv)
/* Change to the CMDPARSE state and return success */
- usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_IDLECMDPARSE), priv->cdb[0]);
+ usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_IDLECMDPARSE),
+ priv->cdb[0]);
priv->thstate = USBMSC_STATE_CMDPARSE;
ret = OK;
}
@@ -1821,7 +1853,7 @@ static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv)
{
FAR struct usbmsc_req_s *privreq;
FAR uint8_t *buf;
- int ret = -EINVAL;
+ int ret;
usbmsc_dumpdata("SCSCI CDB", priv->cdb, priv->cdblen);
@@ -1833,8 +1865,8 @@ static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv)
/* If there no request structures available, then just return an error.
* This will cause us to remain in the CMDPARSE state. When a request is
- * returned, the worker thread will be awakened in the USBMSC_STATE_CMDPARSE
- * and we will be called again.
+ * returned, the worker thread will be awakened in the
+ * USBMSC_STATE_CMDPARSE and we will be called again.
*/
if (!privreq)
@@ -1858,196 +1890,203 @@ static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv)
/* Get exclusive access to the block driver */
- usbmsc_scsi_lock(priv);
+ ret = usbmsc_scsi_lock(priv);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ ret = -EINVAL;
+
switch (priv->cdb[0])
{
- case SCSI_CMD_TESTUNITREADY: /* 0x00 Mandatory */
+ case SCSI_CMD_TESTUNITREADY: /* 0x00 Mandatory */
ret = usbmsc_cmdtestunitready(priv);
break;
- /* case SCSI_CMD_REZEROUNIT: * 0x01 Obsolete
- * * 0x02 Vendor-specific
+ /* case SCSI_CMD_REZEROUNIT: 0x01 Obsolete
+ * 0x02 Vendor-specific
*/
- case SCSI_CMD_REQUESTSENSE: /* 0x03 Mandatory */
+ case SCSI_CMD_REQUESTSENSE: /* 0x03 Mandatory */
ret = usbmsc_cmdrequestsense(priv, buf);
break;
- /* case SCSI_CMD_FORMAT_UNIT: * 0x04 Mandatory, but not impl.
- * * 0x05 Vendor specific
- * * 0x06 Vendor specific
- * case SCSI_CMD_REASSIGNBLOCKS: * 0x07 Optional
+ /* case SCSI_CMD_FORMAT_UNIT: 0x04 Mandatory, but not impl.
+ * 0x05 Vendor specific
+ * 0x06 Vendor specific
+ * case SCSI_CMD_REASSIGNBLOCKS: 0x07 Optional
*/
- case SCSI_CMD_READ6: /* 0x08 Mandatory */
+ case SCSI_CMD_READ6: /* 0x08 Mandatory */
ret = usbmsc_cmdread6(priv);
break;
- /* * 0x09 Vendor specific */
+ /* 0x09 Vendor specific */
- case SCSI_CMD_WRITE6: /* 0x0a Optional */
+ case SCSI_CMD_WRITE6: /* 0x0a Optional */
ret = usbmsc_cmdwrite6(priv);
break;
- /* case SCSI_CMD_SEEK6: * 0x0b Obsolete
- * * 0x0c-0x10 Vendor specific
- * case SCSI_CMD_SPACE6: * 0x11 Vendor specific
+ /* case SCSI_CMD_SEEK6: 0x0b Obsolete
+ * 0x0c-0x10 Vendor specific
+ * case SCSI_CMD_SPACE6: 0x11 Vendor specific
*/
- case SCSI_CMD_INQUIRY: /* 0x12 Mandatory */
+ case SCSI_CMD_INQUIRY: /* 0x12 Mandatory */
ret = usbmsc_cmdinquiry(priv, buf);
break;
- /* * 0x13-0x14 Vendor specific */
+ /* 0x13-0x14 Vendor specific */
- case SCSI_CMD_MODESELECT6: /* 0x15 Optional */
+ case SCSI_CMD_MODESELECT6: /* 0x15 Optional */
ret = usbmsc_cmdmodeselect6(priv);
break;
- /* case SCSI_CMD_RESERVE6: * 0x16 Obsolete
- * case SCSI_CMD_RELEASE6: * 0x17 Obsolete
- * case SCSI_CMD_COPY: * 0x18 Obsolete
- * * 0x19 Vendor specific
+ /* case SCSI_CMD_RESERVE6: 0x16 Obsolete
+ * case SCSI_CMD_RELEASE6: 0x17 Obsolete
+ * case SCSI_CMD_COPY: 0x18 Obsolete
+ * 0x19 Vendor specific
*/
- case SCSI_CMD_MODESENSE6: /* 0x1a Optional */
+ case SCSI_CMD_MODESENSE6: /* 0x1a Optional */
ret = usbmsc_cmdmodesense6(priv, buf);
break;
- case SCSI_CMD_STARTSTOPUNIT: /* 0x1b Optional */
+ case SCSI_CMD_STARTSTOPUNIT: /* 0x1b Optional */
ret = usbmsc_cmdstartstopunit(priv);
break;
- /* case SCSI_CMD_RECEIVEDIAGNOSTICRESULTS: * 0x1c Optional
- * case SCSI_CMD_SENDDIAGNOSTIC: * 0x1d Mandatory, but not impl.
+ /* case SCSI_CMD_RECEIVEDIAGNOSTICRESULTS: 0x1c Optional
+ * case SCSI_CMD_SENDDIAGNOSTIC: 0x1d Mandatory, but not impl.
*/
- case SCSI_CMD_PREVENTMEDIAREMOVAL: /* 0x1e Optional */
+ case SCSI_CMD_PREVENTMEDIAREMOVAL: /* 0x1e Optional */
ret = usbmsc_cmdpreventmediumremoval(priv);
break;
- /* * 0x20-22 Vendor specific */
+ /* 0x20-22 Vendor specific */
- case SCSI_CMD_READFORMATCAPACITIES: /* 0x23 Vend-spec (def. MMC spec) */
+ case SCSI_CMD_READFORMATCAPACITIES: /* 0x23 Vend-spec (def. MMC spec) */
ret = usbmsc_cmdreadformatcapacity(priv, buf);
break;
- /* * 0x24 Vendor specific */
+ /* 0x24 Vendor specific */
- case SCSI_CMD_READCAPACITY10: /* 0x25 Mandatory */
+ case SCSI_CMD_READCAPACITY10: /* 0x25 Mandatory */
ret = usbmsc_cmdreadcapacity10(priv, buf);
break;
- /* * 0x26-27 Vendor specific */
+ /* 0x26-27 Vendor specific */
- case SCSI_CMD_READ10: /* 0x28 Mandatory */
+ case SCSI_CMD_READ10: /* 0x28 Mandatory */
ret = usbmsc_cmdread10(priv);
break;
- /* * 0x29 Vendor specific */
+ /* 0x29 Vendor specific */
- case SCSI_CMD_WRITE10: /* 0x2a Optional */
+ case SCSI_CMD_WRITE10: /* 0x2a Optional */
ret = usbmsc_cmdwrite10(priv);
break;
- /* case SCSI_CMD_SEEK10: * 0x2b Obsolete
- * * 0x2c-2d Vendor specific
- * case SCSI_CMD_WRITEANDVERIFY: * 0x2e Optional
+ /* case SCSI_CMD_SEEK10: 0x2b Obsolete
+ * 0x2c-2d Vendor specific
+ * case SCSI_CMD_WRITEANDVERIFY: 0x2e Optional
*/
- case SCSI_CMD_VERIFY10: /* 0x2f Opt, excpt Windows */
+ case SCSI_CMD_VERIFY10: /* 0x2f Opt, excpt Windows */
ret = usbmsc_cmdverify10(priv);
break;
- /* case SCSI_CMD_SEARCHDATAHIGH: * 0x30 Obsolete
- * case SCSI_CMD_SEARCHDATAEQUAL: * 0x31 Obsolete
- * case SCSI_CMD_SEARCHDATALOW: * 0x32 Obsolete
- * case SCSI_CMD_SETLIMITS10: * 0x33 Obsolete
- * case SCSI_CMD_PREFETCH10: * 0x34 Optional
+ /* case SCSI_CMD_SEARCHDATAHIGH: 0x30 Obsolete
+ * case SCSI_CMD_SEARCHDATAEQUAL: 0x31 Obsolete
+ * case SCSI_CMD_SEARCHDATALOW: 0x32 Obsolete
+ * case SCSI_CMD_SETLIMITS10: 0x33 Obsolete
+ * case SCSI_CMD_PREFETCH10: 0x34 Optional
*/
- case SCSI_CMD_SYNCHCACHE10: /* 0x35 Optional */
+ case SCSI_CMD_SYNCHCACHE10: /* 0x35 Optional */
ret = usbmsc_cmdsynchronizecache10(priv);
break;
- /* case SCSI_CMD_LOCKCACHE: * 0x36 Obsolete
- * case SCSI_CMD_READDEFECTDATA10: * 0x37 Optional
- * case SCSI_CMD_COMPARE: * 0x39 Obsolete
- * case SCSI_CMD_COPYANDVERIFY: * 0x3a Obsolete
- * case SCSI_CMD_WRITEBUFFER: * 0x3b Optional
- * case SCSI_CMD_READBUFFER: * 0x3c Optional
- * case SCSI_CMD_READLONG10: * 0x3e Optional
- * case SCSI_CMD_WRITELONG10: * 0x3f Optional
- * case SCSI_CMD_CHANGEDEFINITION: * 0x40 Obsolete
- * case SCSI_CMD_WRITESAME10: * 0x41 Optional
- * case SCSI_CMD_LOGSELECT: * 0x4c Optional
- * case SCSI_CMD_LOGSENSE: * 0x4d Optional
- * case SCSI_CMD_XDWRITE10: * 0x50 Optional
- * case SCSI_CMD_XPWRITE10: * 0x51 Optional
- * case SCSI_CMD_XDREAD10: * 0x52 Optional
+ /* case SCSI_CMD_LOCKCACHE: 0x36 Obsolete
+ * case SCSI_CMD_READDEFECTDATA10: 0x37 Optional
+ * case SCSI_CMD_COMPARE: 0x39 Obsolete
+ * case SCSI_CMD_COPYANDVERIFY: 0x3a Obsolete
+ * case SCSI_CMD_WRITEBUFFER: 0x3b Optional
+ * case SCSI_CMD_READBUFFER: 0x3c Optional
+ * case SCSI_CMD_READLONG10: 0x3e Optional
+ * case SCSI_CMD_WRITELONG10: 0x3f Optional
+ * case SCSI_CMD_CHANGEDEFINITION: 0x40 Obsolete
+ * case SCSI_CMD_WRITESAME10: 0x41 Optional
+ * case SCSI_CMD_LOGSELECT: 0x4c Optional
+ * case SCSI_CMD_LOGSENSE: 0x4d Optional
+ * case SCSI_CMD_XDWRITE10: 0x50 Optional
+ * case SCSI_CMD_XPWRITE10: 0x51 Optional
+ * case SCSI_CMD_XDREAD10: 0x52 Optional
*/
- case SCSI_CMD_MODESELECT10: /* 0x55 Optional */
+ case SCSI_CMD_MODESELECT10: /* 0x55 Optional */
ret = usbmsc_cmdmodeselect10(priv);
break;
- /* case SCSI_CMD_RESERVE10: * 0x56 Obsolete
- * case SCSI_CMD_RELEASE10: * 0x57 Obsolete
+ /* case SCSI_CMD_RESERVE10: 0x56 Obsolete
+ * case SCSI_CMD_RELEASE10: 0x57 Obsolete
*/
- case SCSI_CMD_MODESENSE10: /* 0x5a Optional */
+ case SCSI_CMD_MODESENSE10: /* 0x5a Optional */
ret = usbmsc_cmdmodesense10(priv, buf);
break;
- /* case SCSI_CMD_PERSISTENTRESERVEIN: * 0x5e Optional
- * case SCSI_CMD_PERSISTENTRESERVEOUT: * 0x5f Optional
- * case SCSI_CMD_32: * 0x7f Optional
- * case SCSI_CMD_XDWRITEEXTENDED: * 0x80 Obsolete
- * case SCSI_CMD_REBUILD: * 0x81 Obsolete
- * case SCSI_CMD_REGENERATE: * 0x82 Obsolete
- * case SCSI_CMD_EXTENDEDCOPY: * 0x83 Optional
- * case SCSI_CMD_COPYRESULTS: * 0x84 Optional
- * case SCSI_CMD_ACCESSCONTROLIN: * 0x86 Optional
- * case SCSI_CMD_ACCESSCONTROLOUT: * 0x87 Optional
- * case SCSI_CMD_READ16: * 0x88 Optional
- * case SCSI_CMD_WRITE16: * 0x8a Optional
- * case SCSI_CMD_READATTRIBUTE: * 0x8c Optional
- * case SCSI_CMD_WRITEATTRIBUTE: * 0x8d Optional
- * case SCSI_CMD_WRITEANDVERIFY16: * 0x8e Optional
- * case SCSI_CMD_SYNCHCACHE16: * 0x91 Optional
- * case SCSI_CMD_LOCKUNLOCKACACHE: * 0x92 Optional
- * case SCSI_CMD_WRITESAME16: * 0x93 Optional
- * case SCSI_CMD_READCAPACITY16: * 0x9e Optional
- * case SCSI_CMD_READLONG16: * 0x9e Optional
- * case SCSI_CMD_WRITELONG16 * 0x9f Optional
- * case SCSI_CMD_REPORTLUNS: * 0xa0 Mandatory, but no-impl
- * case SCSI_CMD_MAINTENANCEIN: * 0xa3 Optional (SCCS==0)
- * case SCSI_CMD_MAINTENANCEOUT: * 0xa4 Optional (SCCS==0)
- * case SCSI_CMD_MOVEMEDIUM: * 0xa5 ?
- * case SCSI_CMD_MOVEMEDIUMATTACHED: * 0xa7 Optional (MCHNGR==0)
+ /* case SCSI_CMD_PERSISTENTRESERVEIN: 0x5e Optional
+ * case SCSI_CMD_PERSISTENTRESERVEOUT: 0x5f Optional
+ * case SCSI_CMD_32: 0x7f Optional
+ * case SCSI_CMD_XDWRITEEXTENDED: 0x80 Obsolete
+ * case SCSI_CMD_REBUILD: 0x81 Obsolete
+ * case SCSI_CMD_REGENERATE: 0x82 Obsolete
+ * case SCSI_CMD_EXTENDEDCOPY: 0x83 Optional
+ * case SCSI_CMD_COPYRESULTS: 0x84 Optional
+ * case SCSI_CMD_ACCESSCONTROLIN: 0x86 Optional
+ * case SCSI_CMD_ACCESSCONTROLOUT: 0x87 Optional
+ * case SCSI_CMD_READ16: 0x88 Optional
+ * case SCSI_CMD_WRITE16: 0x8a Optional
+ * case SCSI_CMD_READATTRIBUTE: 0x8c Optional
+ * case SCSI_CMD_WRITEATTRIBUTE: 0x8d Optional
+ * case SCSI_CMD_WRITEANDVERIFY16: 0x8e Optional
+ * case SCSI_CMD_SYNCHCACHE16: 0x91 Optional
+ * case SCSI_CMD_LOCKUNLOCKACACHE: 0x92 Optional
+ * case SCSI_CMD_WRITESAME16: 0x93 Optional
+ * case SCSI_CMD_READCAPACITY16: 0x9e Optional
+ * case SCSI_CMD_READLONG16: 0x9e Optional
+ * case SCSI_CMD_WRITELONG16 0x9f Optional
+ * case SCSI_CMD_REPORTLUNS: 0xa0 Mandatory, but no-impl
+ * case SCSI_CMD_MAINTENANCEIN: 0xa3 Optional (SCCS==0)
+ * case SCSI_CMD_MAINTENANCEOUT: 0xa4 Optional (SCCS==0)
+ * case SCSI_CMD_MOVEMEDIUM: 0xa5 ?
+ * case SCSI_CMD_MOVEMEDIUMATTACHED: 0xa7 Optional (MCHNGR==0)
*/
- case SCSI_CMD_READ12: /* 0xa8 Optional */
+ case SCSI_CMD_READ12: /* 0xa8 Optional */
ret = usbmsc_cmdread12(priv);
break;
- case SCSI_CMD_WRITE12: /* 0xaa Optional */
+ case SCSI_CMD_WRITE12: /* 0xaa Optional */
ret = usbmsc_cmdwrite12(priv);
break;
- /* case SCSI_CMD_READMEDIASERIALNUMBER: * 0xab Optional
- * case SCSI_CMD_WRITEANDVERIFY12: * 0xae Optional
- * case SCSI_CMD_VERIFY12: * 0xaf Optional
- * case SCSI_CMD_SETLIMITS12 * 0xb3 Obsolete
- * case SCSI_CMD_READELEMENTSTATUS: * 0xb4 Optional (MCHNGR==0)
- * case SCSI_CMD_READDEFECTDATA12: * 0xb7 Optional
- * case SCSI_CMD_REDUNDANCYGROUPIN: * 0xba Optional
- * case SCSI_CMD_REDUNDANCYGROUPOUT: * 0xbb Optional
- * case SCSI_CMD_SPAREIN: * 0xbc Optional (SCCS==0)
- * case SCSI_CMD_SPAREOUT: * 0xbd Optional (SCCS==0)
- * case SCSI_CMD_VOLUMESETIN: * 0xbe Optional (SCCS==0)
- * case SCSI_CMD_VOLUMESETOUT: * 0xbe Optional (SCCS==0)
- * * 0xc0-0xff Vendor specific
+ /* case SCSI_CMD_READMEDIASERIALNUMBER: 0xab Optional
+ * case SCSI_CMD_WRITEANDVERIFY12: 0xae Optional
+ * case SCSI_CMD_VERIFY12: 0xaf Optional
+ * case SCSI_CMD_SETLIMITS12 0xb3 Obsolete
+ * case SCSI_CMD_READELEMENTSTATUS: 0xb4 Optional (MCHNGR==0)
+ * case SCSI_CMD_READDEFECTDATA12: 0xb7 Optional
+ * case SCSI_CMD_REDUNDANCYGROUPIN: 0xba Optional
+ * case SCSI_CMD_REDUNDANCYGROUPOUT: 0xbb Optional
+ * case SCSI_CMD_SPAREIN: 0xbc Optional (SCCS==0)
+ * case SCSI_CMD_SPAREOUT: 0xbd Optional (SCCS==0)
+ * case SCSI_CMD_VOLUMESETIN: 0xbe Optional (SCCS==0)
+ * case SCSI_CMD_VOLUMESETOUT: 0xbe Optional (SCCS==0)
+ * 0xc0-0xff Vendor specific
*/
default:
@@ -2064,9 +2103,9 @@ static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv)
if (priv->thstate == USBMSC_STATE_CMDPARSE)
{
- /* All commands come through this path (EXCEPT read6/10/12 and write6/10/12).
- * For all other commands, the following setup is expected for the response
- * based on data direction:
+ /* All commands come through this path (EXCEPT read6/10/12 and
+ * write6/10/12). For all other commands, the following setup is
+ * expected for the response based on data direction:
*
* For direction NONE:
* 1. priv->u.alloclen == 0
@@ -2077,13 +2116,14 @@ static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv)
* host to receive the device data. The size of the response
* cannot exceed this value.
* 2. response data is in the request currently at the head of
- * the priv->wrreqlist queue. priv->nreqbytes is set to the length
- * of data in the response.
+ * the priv->wrreqlist queue. priv->nreqbytes is set to the
+ * length of data in the response.
*
* For direction host-to-device
- * At present, there are no supported commands that should have host-to-device
- * transfers (except write6/10/12 and that command logic does not take this
- * path. The 'residue' is left at the full host-to-device data size.
+ * At present, there are no supported commands that should have
+ * host-to-device transfers (except write6/10/12 and that command
+ * logic does not take this path. The 'residue' is left at the full
+ * host-to-device data size.
*
* For all:
* ret set to <0 if an error occurred in parsing the commands.
@@ -2113,12 +2153,13 @@ static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv)
/* On return, we need the following:
*
* 1. Setup for CMDFINISH state if appropriate
- * 2. priv->thstate set to either CMDPARSE if no buffer was available or
- * CMDFINISH to send the response
+ * 2. priv->thstate set to either CMDPARSE if no buffer was
+ * available or CMDFINISH to send the response
* 3. Return OK to continue; <0 to wait for the next event
*/
- usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDFINISH), priv->cdb[0]);
+ usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDPARSECMDFINISH),
+ priv->cdb[0]);
priv->thstate = USBMSC_STATE_CMDFINISH;
ret = OK;
}
@@ -2137,10 +2178,11 @@ static int usbmsc_cmdparsestate(FAR struct usbmsc_dev_s *priv)
* command handling.
*
* Returned Value:
- * If no USBDEV write request is available or certain other errors occur, this
- * function returns a negated errno and stays in the USBMSC_STATE_CMDREAD
- * state. Otherwise, when the new SCSI read command is fully processed,
- * this function sets priv->thstate to USBMSC_STATE_CMDFINISH and returns OK.
+ * If no USBDEV write request is available or certain other errors occur,
+ * this function returns a negated errno and stays in the
+ * USBMSC_STATE_CMDREAD state. Otherwise, when the new SCSI read command
+ * is fully processed, this function sets priv->thstate to
+ * USBMSC_STATE_CMDFINISH and returns OK.
*
* State variables:
* xfrlen - holds the number of sectors read to be read.
@@ -2164,8 +2206,8 @@ static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv)
int ret;
/* Loop transferring data until either (1) all of the data has been
- * transferred, or (2) we have used up all of the write requests that we have
- * available.
+ * transferred, or (2) we have used up all of the write requests that we
+ * have available.
*/
while (priv->u.xfrlen > 0 || priv->nsectbytes > 0)
@@ -2181,7 +2223,8 @@ static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv)
nread = USBMSC_DRVR_READ(lun, priv->iobuffer, priv->sector, 1);
if (nread < 0)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDREADREADFAIL), -nread);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDREADREADFAIL),
+ -nread);
lun->sd = SCSI_KCQME_UNRRE1;
lun->sdinfo = priv->sector;
break;
@@ -2198,10 +2241,10 @@ static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv)
privreq = (FAR struct usbmsc_req_s *)sq_peek(&priv->wrreqlist);
- /* If there no request structures available, then just return an error.
- * This will cause us to remain in the CMDREAD state. When a request is
- * returned, the worker thread will be awakened in the USBMSC_STATE_CMDREAD
- * and we will be called again.
+ /* If there no request structures available, then just return an
+ * error. This will cause us to remain in the CMDREAD state. When a
+ * request is returned, the worker thread will be awakened in the
+ * USBMSC_STATE_CMDREAD and we will be called again.
*/
if (!privreq)
@@ -2213,14 +2256,15 @@ static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv)
req = privreq->req;
- /* Transfer all of the data that will (1) fit into the request buffer, OR (2)
- * all of the data available in the sector buffer.
+ /* Transfer all of the data that will (1) fit into the request buffer,
+ * OR (2) all of the data available in the sector buffer.
*/
src = &priv->iobuffer[lun->sectorsize - priv->nsectbytes];
dest = &req->buf[priv->nreqbytes];
- nbytes = MIN(priv->epbulkin->maxpacket - priv->nreqbytes, priv->nsectbytes);
+ nbytes = MIN(priv->epbulkin->maxpacket - priv->nreqbytes,
+ priv->nsectbytes);
/* Copy the data from the sector buffer to the USB request and update counts */
@@ -2254,14 +2298,16 @@ static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv)
ret = EP_SUBMIT(priv->epbulkin, req);
if (ret != OK)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDREADSUBMIT), (uint16_t)-ret);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDREADSUBMIT),
+ (uint16_t)-ret);
lun->sd = SCSI_KCQME_UNRRE1;
lun->sdinfo = priv->sector;
break;
}
- /* Assume success... residue should probably really be decremented in
- * wrcomplete when we know that the transfer completed successfully.
+ /* Assume success... residue should probably really be decremented
+ * in wrcomplete when we know that the transfer completed
+ * successfully.
*/
priv->residue -= priv->nreqbytes;
@@ -2269,7 +2315,8 @@ static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv)
}
}
- usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDREADCMDFINISH), priv->u.xfrlen);
+ usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDREADCMDFINISH),
+ priv->u.xfrlen);
priv->thstate = USBMSC_STATE_CMDFINISH;
return OK;
}
@@ -2285,10 +2332,11 @@ static int usbmsc_cmdreadstate(FAR struct usbmsc_dev_s *priv)
* command handling.
*
* Returned Value:
- * If no USBDEV write request is available or certain other errors occur, this
- * function returns a negated errno and stays in the USBMSC_STATE_CMDWRITE
- * state. Otherwise, when the new SCSI write command is fully processed,
- * this function sets priv->thstate to USBMSC_STATE_CMDFINISH and returns OK.
+ * If no USBDEV write request is available or certain other errors occur,
+ * this function returns a negated errno and stays in the
+ * USBMSC_STATE_CMDWRITE state. Otherwise, when the new SCSI write
+ * command is fully processed, this function sets priv->thstate to
+ * USBMSC_STATE_CMDFINISH and returns OK.
*
* State variables:
* xfrlen - holds the number of sectors read to be written.
@@ -2329,9 +2377,9 @@ static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv)
leave_critical_section(flags);
/* If there no request data available, then just return an error.
- * This will cause us to remain in the CMDWRITE state. When a filled request is
- * received, the worker thread will be awakened in the USBMSC_STATE_CMDWRITE
- * and we will be called again.
+ * This will cause us to remain in the CMDWRITE state. When a filled
+ * request is received, the worker thread will be awakened in the
+ * USBMSC_STATE_CMDWRITE and we will be called again.
*/
if (!privreq)
@@ -2345,8 +2393,9 @@ static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv)
xfrd = req->xfrd;
priv->nreqbytes = xfrd;
- /* Now loop until all of the data in the read request has been transferred
- * to the block driver OR all of the request data has been transferred.
+ /* Now loop until all of the data in the read request has been
+ * transferred to the block driver OR all of the request data has been
+ * transferred.
*/
while (priv->nreqbytes > 0 && priv->u.xfrlen > 0)
@@ -2370,7 +2419,8 @@ static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv)
{
/* Yes.. Write the next sector */
- nwritten = USBMSC_DRVR_WRITE(lun, priv->iobuffer, priv->sector, 1);
+ nwritten = USBMSC_DRVR_WRITE(lun, priv->iobuffer,
+ priv->sector, 1);
if (nwritten < 0)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDWRITEWRITEFAIL),
@@ -2387,9 +2437,9 @@ static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv)
}
}
- /* In either case, we are finished with this read request and can return it
- * to the endpoint. Then we will go back to the top of the top and attempt
- * to get the next read request.
+ /* In either case, we are finished with this read request and can
+ * return it to the endpoint. Then we will go back to the top of the
+ * top and attempt to get the next read request.
*/
req->len = priv->epbulkout->maxpacket;
@@ -2399,7 +2449,8 @@ static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv)
ret = EP_SUBMIT(priv->epbulkout, req);
if (ret != OK)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDWRITERDSUBMIT), (uint16_t)-ret);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDWRITERDSUBMIT),
+ (uint16_t)-ret);
}
/* Did the host decide to stop early? */
@@ -2412,7 +2463,8 @@ static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv)
}
errout:
- usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDWRITECMDFINISH), priv->u.xfrlen);
+ usbtrace(TRACE_CLASSSTATE(USBMSC_CLASSSTATE_CMDWRITECMDFINISH),
+ priv->u.xfrlen);
priv->thstate = USBMSC_STATE_CMDFINISH;
return OK;
}
@@ -2426,10 +2478,11 @@ errout:
* command has finished but before status has been returned.
*
* Returned Value:
- * If no USBDEV write request is available or certain other errors occur, this
- * function returns a negated errno and stays in the USBMSC_STATE_CMDFINISH
- * state. Otherwise, when the command is fully processed, this function
- * sets priv->thstate to USBMSC_STATE_CMDSTATUS and returns OK.
+ * If no USBDEV write request is available or certain other errors occur,
+ * this function returns a negated errno and stays in the
+ * USBMSC_STATE_CMDFINISH state. Otherwise, when the command is fully
+ * processed, this function sets priv->thstate to USBMSC_STATE_CMDSTATUS
+ * and returns OK.
*
****************************************************************************/
@@ -2479,7 +2532,8 @@ static int usbmsc_cmdfinishstate(FAR struct usbmsc_dev_s *priv)
*/
flags = enter_critical_section();
- privreq = (FAR struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist);
+ privreq = (FAR struct usbmsc_req_s *)
+ sq_remfirst(&priv->wrreqlist);
leave_critical_section(flags);
/* Send the write request */
@@ -2507,7 +2561,8 @@ static int usbmsc_cmdfinishstate(FAR struct usbmsc_dev_s *priv)
#ifdef USBMSC_STALL_RACEWAR
/* (See description of the workaround at the top of the file).
- * First, wait for the transfer to complete, then stall the endpoint
+ * First, wait for the transfer to complete, then stall the
+ * endpoint
*/
nxsig_usleep (100000);
@@ -2598,9 +2653,9 @@ static int usbmsc_cmdstatusstate(FAR struct usbmsc_dev_s *priv)
leave_critical_section(flags);
/* If there no request structures available, then just return an error.
- * This will cause us to remain in the CMDSTATUS status. When a request is
- * returned, the worker thread will be awakened in the USBMSC_STATE_CMDSTATUS
- * and we will be called again.
+ * This will cause us to remain in the CMDSTATUS status. When a request
+ * is returned, the worker thread will be awakened in the
+ * USBMSC_STATE_CMDSTATUS and we will be called again.
*/
if (!privreq)
@@ -2657,7 +2712,8 @@ static int usbmsc_cmdstatusstate(FAR struct usbmsc_dev_s *priv)
ret = EP_SUBMIT(priv->epbulkin, req);
if (ret < 0)
{
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SNDSTATUSSUBMIT), (uint16_t)-ret);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SNDSTATUSSUBMIT),
+ (uint16_t)-ret);
flags = enter_critical_section();
sq_addlast((FAR sq_entry_t *)privreq, &priv->wrreqlist);
leave_critical_section(flags);
@@ -2700,17 +2756,33 @@ int usbmsc_scsi_main(int argc, char *argv[])
g_usbmsc_handoff = NULL;
usbmsc_synch_signal(priv);
- /* This thread is started before the USB storage class is fully initialized.
- * wait here until we are told to begin. Start in the NOTINITIALIZED state
+ /* Get exclusive access to SCSI state data */
+
+ ret = usbmsc_scsi_lock(priv);
+ if (ret < 0)
+ {
+ return EXIT_FAILURE;
+ }
+
+ /* This thread is started before the USB storage class is fully
+ * initialized. Wait here until we are told to begin. Start in the
+ * NOTINITIALIZED state
*/
- uinfo("Waiting to be signalled\n");
- usbmsc_scsi_lock(priv);
+ uinfo("Waiting to be signaled\n");
+
priv->thstate = USBMSC_STATE_STARTED;
while ((priv->theventset & USBMSC_EVENT_READY) == 0 &&
(priv->theventset & USBMSC_EVENT_TERMINATEREQUEST) == 0)
{
- usbmsc_scsi_wait(priv);
+ ret = usbmsc_scsi_wait(priv);
+ if (ret < 0)
+ {
+ /* The thread has been canceled */
+
+ usbmsc_scsi_unlock(priv);
+ return EXIT_FAILURE;
+ }
}
uinfo("Running\n");
@@ -2728,14 +2800,28 @@ int usbmsc_scsi_main(int argc, char *argv[])
{
/* Wait for some interesting event. Note that we must both take the
* lock (to eliminate race conditions with other threads) and disable
- * interrupts (to eliminate race conditions with USB interrupt handling.
+ * interrupts (to eliminate race conditions with USB interrupt
+ * handling.
*/
- usbmsc_scsi_lock(priv);
+ ret = usbmsc_scsi_lock(priv);
+ if (ret < 0)
+ {
+ return EXIT_FAILURE;
+ }
+
flags = enter_critical_section();
if (priv->theventset == USBMSC_EVENT_NOEVENTS)
{
- usbmsc_scsi_wait(priv);
+ ret = usbmsc_scsi_wait(priv);
+ if (ret < 0)
+ {
+ /* The thread has been canceled */
+
+ leave_critical_section(flags);
+ usbmsc_scsi_unlock(priv);
+ return EXIT_FAILURE;
+ }
}
/* Sample any events before re-enabling interrupts. Any events that
@@ -2749,12 +2835,13 @@ int usbmsc_scsi_main(int argc, char *argv[])
/* Were we awakened by some event that requires immediate action?
*
- * - The USBMSC_EVENT_DISCONNECT is signalled from the disconnect method
- * after all transfers have been stopped, when the host is disconnected.
+ * - The USBMSC_EVENT_DISCONNECT is signaled from the disconnect
+ * method after all transfers have been stopped, when the host is
+ * disconnected.
*
- * - The CUSBMSC_EVENT_RESET is signalled when the bulk-storage-specific
- * USBMSC_REQ_MSRESET EP0 setup received. We must stop the current
- * operation and reinialize state.
+ * - The CUSBMSC_EVENT_RESET is signaled when the bulk-storage
+ * specific USBMSC_REQ_MSRESET EP0 setup received. We must stop the
+ * current operation and reinitialize state.
*
* - The USBMSC_EVENT_CFGCHANGE is signaled when the EP0 setup logic
* receives a valid USB_REQ_SETCONFIGURATION request
@@ -2762,7 +2849,7 @@ int usbmsc_scsi_main(int argc, char *argv[])
* - The USBMSC_EVENT_IFCHANGE is signaled when the EP0 setup logic
* receives a valid USB_REQ_SETINTERFACE request
*
- * - The USBMSC_EVENT_ABORTBULKOUT event is signalled by the CMDFINISH
+ * - The USBMSC_EVENT_ABORTBULKOUT event is signaled by the CMDFINISH
* logic when there is a residue after processing a host-to-device
* transfer. We need to discard all incoming request.
*
@@ -2799,7 +2886,8 @@ int usbmsc_scsi_main(int argc, char *argv[])
/* Loop processing each SCSI command state. Each state handling
* function will do the following:
*
- * - If it must block for an event, it will return a negated errno value
+ * - If it must block for an event, it will return a negated errno
+ * value
* - If it completes the processing for that state, it will (1) set
* the next appropriate state value and (2) return OK.
*
@@ -2812,35 +2900,36 @@ int usbmsc_scsi_main(int argc, char *argv[])
{
switch (priv->thstate)
{
- case USBMSC_STATE_IDLE: /* Started and waiting for commands */
+ case USBMSC_STATE_IDLE: /* Started and waiting for commands */
ret = usbmsc_idlestate(priv);
break;
- case USBMSC_STATE_CMDPARSE: /* Parsing the received a command */
+ case USBMSC_STATE_CMDPARSE: /* Parsing the received a command */
ret = usbmsc_cmdparsestate(priv);
break;
- case USBMSC_STATE_CMDREAD: /* Continuing to process a SCSI read command */
+ case USBMSC_STATE_CMDREAD: /* Continuing to process a SCSI read command */
ret = usbmsc_cmdreadstate(priv);
break;
- case USBMSC_STATE_CMDWRITE: /* Continuing to process a SCSI write command */
+ case USBMSC_STATE_CMDWRITE: /* Continuing to process a SCSI write command */
ret = usbmsc_cmdwritestate(priv);
break;
- case USBMSC_STATE_CMDFINISH: /* Finish command processing */
+ case USBMSC_STATE_CMDFINISH: /* Finish command processing */
ret = usbmsc_cmdfinishstate(priv);
break;
- case USBMSC_STATE_CMDSTATUS: /* Processing the status phase of a command */
+ case USBMSC_STATE_CMDSTATUS: /* Processing the status phase of a command */
ret = usbmsc_cmdstatusstate(priv);
break;
- case USBMSC_STATE_NOTSTARTED: /* Thread has not yet been started */
- case USBMSC_STATE_STARTED: /* Started, but is not yet initialized */
- case USBMSC_STATE_TERMINATED: /* Thread has exitted */
+ case USBMSC_STATE_NOTSTARTED: /* Thread has not yet been started */
+ case USBMSC_STATE_STARTED: /* Started, but is not yet initialized */
+ case USBMSC_STATE_TERMINATED: /* Thread has exited */
default:
- usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INVALIDSTATE), priv->thstate);
+ usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INVALIDSTATE),
+ priv->thstate);
priv->thstate = USBMSC_STATE_IDLE;
ret = OK;
break;
@@ -2892,7 +2981,7 @@ void usbmsc_scsi_signal(FAR struct usbmsc_dev_s *priv)
*
****************************************************************************/
-void usbmsc_scsi_lock(FAR struct usbmsc_dev_s *priv)
+int usbmsc_scsi_lock(FAR struct usbmsc_dev_s *priv)
{
- nxsem_wait_uninterruptible(&priv->thlock);
+ return nxsem_wait_uninterruptible(&priv->thlock);
}