libc/stream:Add mtd backend stream.
Signed-off-by: 田昕 <tianxin7@xiaomi.com>
This commit is contained in:
parent
0ec4b0a149
commit
28739b8b8a
@ -139,10 +139,6 @@ static const struct esp32c3_mtd_dev_s g_esp32c3_spiflash_encrypt =
|
||||
}
|
||||
};
|
||||
|
||||
/* Ensure exclusive access to the driver */
|
||||
|
||||
static mutex_t g_lock = NXMUTEX_INITIALIZER;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -170,6 +166,7 @@ static int esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
|
||||
uint32_t offset = startblock * MTD_ERASE_SIZE;
|
||||
uint32_t nbytes = nblocks * MTD_ERASE_SIZE;
|
||||
struct esp32c3_mtd_dev_s *priv = (struct esp32c3_mtd_dev_s *)dev;
|
||||
irqstate_t flags;
|
||||
|
||||
if ((offset > MTD_SIZE(priv)) || ((offset + nbytes) > MTD_SIZE(priv)))
|
||||
{
|
||||
@ -182,14 +179,9 @@ static int esp32c3_erase(struct mtd_dev_s *dev, off_t startblock,
|
||||
finfo("spi_flash_erase_range(0x%x, %d)\n", offset, nbytes);
|
||||
#endif
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_erase_range(offset, nbytes);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -231,6 +223,7 @@ static ssize_t esp32c3_read(struct mtd_dev_s *dev, off_t offset,
|
||||
size_t nbytes, uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
@ -238,16 +231,9 @@ static ssize_t esp32c3_read(struct mtd_dev_s *dev, off_t offset,
|
||||
finfo("spi_flash_read(0x%x, %p, %d)\n", offset, buffer, nbytes);
|
||||
#endif
|
||||
|
||||
/* Acquire the mutex. */
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_read(offset, buffer, nbytes);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -284,6 +270,7 @@ static ssize_t esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
|
||||
@ -292,14 +279,9 @@ static ssize_t esp32c3_bread(struct mtd_dev_s *dev, off_t startblock,
|
||||
finfo("spi_flash_read(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_read(addr, buffer, size);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -337,6 +319,7 @@ static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
|
||||
uint8_t *buffer)
|
||||
{
|
||||
ssize_t ret;
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer);
|
||||
@ -345,16 +328,9 @@ static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
|
||||
nbytes);
|
||||
#endif
|
||||
|
||||
/* Acquire the mutex. */
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_read_encrypted(offset, buffer, nbytes);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -393,6 +369,7 @@ static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks,
|
||||
@ -401,14 +378,9 @@ static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
|
||||
finfo("spi_flash_read_encrypted(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_read_encrypted(addr, buffer, size);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -444,6 +416,7 @@ static ssize_t esp32c3_write(struct mtd_dev_s *dev, off_t offset,
|
||||
{
|
||||
ssize_t ret;
|
||||
struct esp32c3_mtd_dev_s *priv = (struct esp32c3_mtd_dev_s *)dev;
|
||||
irqstate_t flags;
|
||||
|
||||
ASSERT(buffer);
|
||||
|
||||
@ -458,16 +431,9 @@ static ssize_t esp32c3_write(struct mtd_dev_s *dev, off_t offset,
|
||||
finfo("spi_flash_write(0x%x, %p, %d)\n", offset, buffer, nbytes);
|
||||
#endif
|
||||
|
||||
/* Acquire the mutex. */
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_write(offset, buffer, nbytes);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -505,6 +471,7 @@ static ssize_t esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
|
||||
@ -513,14 +480,9 @@ static ssize_t esp32c3_bwrite(struct mtd_dev_s *dev, off_t startblock,
|
||||
finfo("spi_flash_write(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_write(addr, buffer, size);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
@ -560,6 +522,7 @@ static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
|
||||
ssize_t ret;
|
||||
uint32_t addr = startblock * MTD_BLK_SIZE;
|
||||
uint32_t size = nblocks * MTD_BLK_SIZE;
|
||||
irqstate_t flags;
|
||||
|
||||
#ifdef CONFIG_ESP32C3_STORAGE_MTD_DEBUG
|
||||
finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock,
|
||||
@ -568,14 +531,9 @@ static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev,
|
||||
finfo("spi_flash_write_encrypted(0x%x, %p, %d)\n", addr, buffer, size);
|
||||
#endif
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
ret = spi_flash_write_encrypted(addr, buffer, size);
|
||||
nxmutex_unlock(&g_lock);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
|
@ -31,6 +31,9 @@
|
||||
#include <stdio.h>
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
#include <nuttx/fs/fs.h>
|
||||
#ifdef CONFIG_MTD
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -210,6 +213,16 @@ struct lib_blkoutstream_s
|
||||
};
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD)
|
||||
struct lib_mtdoutstream_s
|
||||
{
|
||||
struct lib_outstream_s public;
|
||||
FAR struct inode *inode;
|
||||
struct mtd_geometry_s geo;
|
||||
FAR unsigned char *cache;
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
@ -427,6 +440,46 @@ int lib_blkoutstream_open(FAR struct lib_blkoutstream_s *stream,
|
||||
void lib_blkoutstream_close(FAR struct lib_blkoutstream_s *stream);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_mtdoutstream_open
|
||||
*
|
||||
* Description:
|
||||
* mtd driver stream backend
|
||||
*
|
||||
* Input Parameters:
|
||||
* stream - User allocated, uninitialized instance of struct
|
||||
* lib_mtdoutstream_s to be initialized.
|
||||
* name - The full path of mtd device.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD)
|
||||
int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream,
|
||||
FAR const char *name);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_mtdoutstream_close
|
||||
*
|
||||
* Description:
|
||||
* close mtd driver stream backend
|
||||
*
|
||||
* Input Parameters:
|
||||
* stream - User allocated, uninitialized instance of struct
|
||||
* lib_mtdoutstream_s to be initialized.
|
||||
*
|
||||
* Returned Value:
|
||||
* None (User allocated instance initialized).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD)
|
||||
void lib_mtdoutstream_close(FAR struct lib_mtdoutstream_s *stream);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_noflush
|
||||
*
|
||||
|
@ -25,7 +25,7 @@ CSRCS += lib_meminstream.c lib_memoutstream.c lib_memsistream.c
|
||||
CSRCS += lib_memsostream.c lib_lowoutstream.c lib_rawinstream.c
|
||||
CSRCS += lib_rawoutstream.c lib_rawsistream.c lib_rawsostream.c
|
||||
CSRCS += lib_zeroinstream.c lib_nullinstream.c lib_nulloutstream.c
|
||||
CSRCS += lib_libnoflush.c lib_libsnoflush.c
|
||||
CSRCS += lib_mtdoutstream.c lib_libnoflush.c lib_libsnoflush.c
|
||||
|
||||
# The remaining sources files depend upon C streams
|
||||
|
||||
|
301
libs/libc/stream/lib_mtdoutstream.c
Normal file
301
libs/libc/stream/lib_mtdoutstream.c
Normal file
@ -0,0 +1,301 @@
|
||||
/****************************************************************************
|
||||
* libs/libc/stream/lib_mtdoutstream.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <nuttx/streams.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
#include "libc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtdoutstream_flush
|
||||
****************************************************************************/
|
||||
|
||||
static int mtdoutstream_flush(FAR struct lib_outstream_s *this)
|
||||
{
|
||||
FAR struct lib_mtdoutstream_s *stream =
|
||||
(FAR struct lib_mtdoutstream_s *)this;
|
||||
size_t erasesize = stream->geo.erasesize;
|
||||
size_t nblkpererase = erasesize / stream->geo.blocksize;
|
||||
int ret = OK;
|
||||
|
||||
if (this->nput % erasesize > 0)
|
||||
{
|
||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||
/* if byte write, flush won't be needed */
|
||||
|
||||
if (stream->inode->u.i_mtd->write == NULL)
|
||||
#endif
|
||||
{
|
||||
ret = MTD_ERASE(stream->inode->u.i_mtd, this->nput / erasesize, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = MTD_BWRITE(stream->inode->u.i_mtd,
|
||||
this->nput / erasesize * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtdoutstream_puts
|
||||
****************************************************************************/
|
||||
|
||||
static int mtdoutstream_puts(FAR struct lib_outstream_s *this,
|
||||
FAR const void *buf, int len)
|
||||
{
|
||||
FAR struct lib_mtdoutstream_s *stream =
|
||||
(FAR struct lib_mtdoutstream_s *)this;
|
||||
size_t erasesize = stream->geo.erasesize;
|
||||
size_t nblkpererase = erasesize / stream->geo.blocksize;
|
||||
FAR struct inode *inode = stream->inode;
|
||||
FAR const unsigned char *ptr = buf;
|
||||
size_t remain = len;
|
||||
int ret;
|
||||
|
||||
if (this->nput + len > erasesize * stream->geo.neraseblocks)
|
||||
{
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||
if (stream->inode->u.i_mtd->write != NULL)
|
||||
{
|
||||
if (this->nput % stream->geo.erasesize == 0)
|
||||
{
|
||||
ret = MTD_ERASE(inode->u.i_mtd,
|
||||
this->nput / stream->geo.erasesize, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = MTD_WRITE(inode->u.i_mtd, this->nput, len, buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
this->nput += len;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
while (remain > 0)
|
||||
{
|
||||
size_t sblock = this->nput / erasesize;
|
||||
size_t offset = this->nput % erasesize;
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
size_t copyin = offset + remain > erasesize ?
|
||||
erasesize - offset : remain;
|
||||
|
||||
memcpy(stream->cache + offset, ptr, copyin);
|
||||
|
||||
ptr += copyin;
|
||||
offset += copyin;
|
||||
this->nput += copyin;
|
||||
remain -= copyin;
|
||||
|
||||
if (offset == erasesize)
|
||||
{
|
||||
ret = MTD_ERASE(inode->u.i_mtd, sblock, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (remain < erasesize)
|
||||
{
|
||||
/* erase content to all 0 before caching,
|
||||
* so no random content will be flushed
|
||||
*/
|
||||
|
||||
memset(stream->cache, 0, stream->geo.erasesize);
|
||||
memcpy(stream->cache, ptr, remain);
|
||||
this->nput += remain;
|
||||
remain = 0;
|
||||
}
|
||||
else if (remain >= erasesize)
|
||||
{
|
||||
size_t copyin = (remain / erasesize) * erasesize;
|
||||
|
||||
ret = MTD_ERASE(inode->u.i_mtd, sblock,
|
||||
remain / erasesize);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase,
|
||||
remain / erasesize * nblkpererase,
|
||||
ptr);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ptr += copyin;
|
||||
this->nput += copyin;
|
||||
remain -= copyin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_mtdoutstream_close
|
||||
*
|
||||
* Description:
|
||||
* close mtd driver stream backend
|
||||
*
|
||||
* Input Parameters:
|
||||
* stream - User allocated, uninitialized instance of struct
|
||||
* lib_mtdoutstream_s to be initialized.
|
||||
*
|
||||
* Returned Value:
|
||||
* None (User allocated instance initialized).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void lib_mtdoutstream_close(FAR struct lib_mtdoutstream_s *stream)
|
||||
{
|
||||
if (stream != NULL)
|
||||
{
|
||||
if (stream->inode != NULL)
|
||||
{
|
||||
close_mtddriver(stream->inode);
|
||||
stream->inode = NULL;
|
||||
}
|
||||
|
||||
if (stream->cache != NULL)
|
||||
{
|
||||
lib_free(stream->cache);
|
||||
stream->cache = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_mtdoutstream_open
|
||||
*
|
||||
* Description:
|
||||
* mtd driver stream backend
|
||||
*
|
||||
* Input Parameters:
|
||||
* stream - User allocated, uninitialized instance of struct
|
||||
* lib_mtdoutstream_s to be initialized.
|
||||
* name - The full path of mtd device.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero on success or a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream,
|
||||
FAR const char *name)
|
||||
{
|
||||
FAR struct inode *node = NULL;
|
||||
int ret;
|
||||
|
||||
if (stream == NULL || name == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = find_mtddriver(name, &node);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(stream, 0, sizeof(*stream));
|
||||
|
||||
if (node->u.i_mtd->ioctl == NULL ||
|
||||
node->u.i_mtd->erase == NULL ||
|
||||
node->u.i_mtd->bwrite == NULL ||
|
||||
node->u.i_mtd->ioctl(node->u.i_mtd, MTDIOC_GEOMETRY,
|
||||
(unsigned long)&stream->geo) < 0 ||
|
||||
stream->geo.blocksize <= 0 ||
|
||||
stream->geo.erasesize <= 0 ||
|
||||
stream->geo.neraseblocks <= 0)
|
||||
{
|
||||
close_mtddriver(node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||
if (node->u.i_mtd->write == NULL)
|
||||
#endif
|
||||
{
|
||||
stream->cache = lib_zalloc(stream->geo.erasesize);
|
||||
if (stream->cache == NULL)
|
||||
{
|
||||
close_mtddriver(node);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
stream->inode = node;
|
||||
stream->public.puts = mtdoutstream_puts;
|
||||
stream->public.flush = mtdoutstream_flush;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MTD */
|
Loading…
Reference in New Issue
Block a user