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/.
This commit is contained in:
Gregory Nutt 2020-04-01 10:13:52 -06:00 committed by Alan Carvalho de Assis
parent a7415058e5
commit 9ff1795760
8 changed files with 727 additions and 549 deletions

View File

@ -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)

View File

@ -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

View File

@ -1,35 +1,20 @@
/****************************************************************************
* drivers/serial/ptmx.c
*
* Copyright (C) 2016-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@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.
*
****************************************************************************/
@ -116,22 +101,6 @@ static struct ptmx_dev_s g_ptmx;
* Private Functions
****************************************************************************/
/****************************************************************************
* 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
*
@ -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 */
}

View File

@ -1,35 +1,20 @@
/****************************************************************************
* drivers/serial/pty.c
*
* Copyright (C) 2016-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@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.
*/
{
/* 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);
}
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;
}

View File

@ -1,35 +1,20 @@
/****************************************************************************
* drivers/timers/pwm.c
*
* Copyright (C) 2011-2013, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@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);

View File

@ -1,12 +1,25 @@
/****************************************************************************
* drivers/usbdev/usbmsc.c
*
* Copyright (C) 2008-2012, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Mass storage class device. Bulk-only with SCSI subclass.
*
* References:
* 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
*
* 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:
* "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
@ -173,9 +158,6 @@ FAR struct usbmsc_dev_s *g_usbmsc_handoff;
* Private Functions
****************************************************************************/
/****************************************************************************
* Class Driver Support
****************************************************************************/
/****************************************************************************
* Name: usbmsc_ep0incomplete
*
@ -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;
}
}
}

View File

@ -1,37 +1,21 @@
/****************************************************************************
* drivers/usbdev/usbmsc.h
*
* Copyright (C) 2008-2013, 2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Mass storage class device. Bulk-only with SCSI subclass.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 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
*
* 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.
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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
/****************************************************************************

File diff suppressed because it is too large Load Diff