1beacf11bSopenharmony_ci/**************************************************************************** 2beacf11bSopenharmony_ci * drivers/pipes/pipe.c 3beacf11bSopenharmony_ci * 4beacf11bSopenharmony_ci * Licensed to the Apache Software Foundation (ASF) under one or more 5beacf11bSopenharmony_ci * contributor license agreements. See the NOTICE file distributed with 6beacf11bSopenharmony_ci * this work for additional information regarding copyright ownership. The 7beacf11bSopenharmony_ci * ASF licenses this file to you under the Apache License, Version 2.0 (the 8beacf11bSopenharmony_ci * "License"); you may not use this file except in compliance with the 9beacf11bSopenharmony_ci * License. You may obtain a copy of the License at 10beacf11bSopenharmony_ci * 11beacf11bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12beacf11bSopenharmony_ci * 13beacf11bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14beacf11bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15beacf11bSopenharmony_ci * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16beacf11bSopenharmony_ci * License for the specific language governing permissions and limitations 17beacf11bSopenharmony_ci * under the License. 18beacf11bSopenharmony_ci * 19beacf11bSopenharmony_ci ****************************************************************************/ 20beacf11bSopenharmony_ci 21beacf11bSopenharmony_ci/**************************************************************************** 22beacf11bSopenharmony_ci * Included Files 23beacf11bSopenharmony_ci ****************************************************************************/ 24beacf11bSopenharmony_ci#include "pipe_common.h" 25beacf11bSopenharmony_ci#include <assert.h> 26beacf11bSopenharmony_ci#include <errno.h> 27beacf11bSopenharmony_ci#include <fcntl.h> 28beacf11bSopenharmony_ci#include <semaphore.h> 29beacf11bSopenharmony_ci#include <stdio.h> 30beacf11bSopenharmony_ci#include <sys/types.h> 31beacf11bSopenharmony_ci#include <unistd.h> 32beacf11bSopenharmony_ci#include "fs/driver.h" 33beacf11bSopenharmony_ci#include "los_init.h" 34beacf11bSopenharmony_ci 35beacf11bSopenharmony_ci#if CONFIG_DEV_PIPE_SIZE > 0 36beacf11bSopenharmony_ci 37beacf11bSopenharmony_ci/**************************************************************************** 38beacf11bSopenharmony_ci * Pre-processor Definitions 39beacf11bSopenharmony_ci ****************************************************************************/ 40beacf11bSopenharmony_ci 41beacf11bSopenharmony_ci#define MAX_PIPES 32 42beacf11bSopenharmony_ci 43beacf11bSopenharmony_ci/**************************************************************************** 44beacf11bSopenharmony_ci * Private Types 45beacf11bSopenharmony_ci ****************************************************************************/ 46beacf11bSopenharmony_ci 47beacf11bSopenharmony_ci/**************************************************************************** 48beacf11bSopenharmony_ci * Private Function Prototypes 49beacf11bSopenharmony_ci ****************************************************************************/ 50beacf11bSopenharmony_ci 51beacf11bSopenharmony_cistatic int pipe_close(struct file *filep); 52beacf11bSopenharmony_ci#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS 53beacf11bSopenharmony_ciint pipe_unlink(struct Vnode *priv); 54beacf11bSopenharmony_ci#endif 55beacf11bSopenharmony_ci 56beacf11bSopenharmony_ci/**************************************************************************** 57beacf11bSopenharmony_ci * Private Data 58beacf11bSopenharmony_ci ****************************************************************************/ 59beacf11bSopenharmony_ci 60beacf11bSopenharmony_cistatic ssize_t pipe_map(struct file* filep, LosVmMapRegion *region) 61beacf11bSopenharmony_ci{ 62beacf11bSopenharmony_ci PRINTK("%s %d, mmap is not support\n", __FUNCTION__, __LINE__); 63beacf11bSopenharmony_ci return 0; 64beacf11bSopenharmony_ci} 65beacf11bSopenharmony_ci 66beacf11bSopenharmony_cistatic const struct file_operations_vfs pipe_fops = 67beacf11bSopenharmony_ci{ 68beacf11bSopenharmony_ci .open = pipecommon_open, /* open */ 69beacf11bSopenharmony_ci .close = pipe_close, /* close */ 70beacf11bSopenharmony_ci .read = pipecommon_read, /* read */ 71beacf11bSopenharmony_ci .write = pipecommon_write, /* write */ 72beacf11bSopenharmony_ci .seek = NULL, /* seek */ 73beacf11bSopenharmony_ci .ioctl = NULL, /* ioctl */ 74beacf11bSopenharmony_ci .mmap = pipe_map, /* mmap */ 75beacf11bSopenharmony_ci .poll = pipecommon_poll, /* poll */ 76beacf11bSopenharmony_ci#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS 77beacf11bSopenharmony_ci .unlink = pipe_unlink, /* unlink */ 78beacf11bSopenharmony_ci#endif 79beacf11bSopenharmony_ci}; 80beacf11bSopenharmony_ci 81beacf11bSopenharmony_cistatic sem_t g_pipesem = {NULL}; 82beacf11bSopenharmony_cistatic uint32_t g_pipeset = 0; 83beacf11bSopenharmony_cistatic uint32_t g_pipecreated = 0; 84beacf11bSopenharmony_ci 85beacf11bSopenharmony_ci/**************************************************************************** 86beacf11bSopenharmony_ci * Private Functions 87beacf11bSopenharmony_ci ****************************************************************************/ 88beacf11bSopenharmony_ci 89beacf11bSopenharmony_ci/**************************************************************************** 90beacf11bSopenharmony_ci * Name: pipe_allocate 91beacf11bSopenharmony_ci ****************************************************************************/ 92beacf11bSopenharmony_ci 93beacf11bSopenharmony_cistatic inline int pipe_allocate(void) 94beacf11bSopenharmony_ci{ 95beacf11bSopenharmony_ci int pipeno; 96beacf11bSopenharmony_ci int ret = -ENFILE; 97beacf11bSopenharmony_ci 98beacf11bSopenharmony_ci for (pipeno = 0; pipeno < MAX_PIPES; pipeno++) 99beacf11bSopenharmony_ci { 100beacf11bSopenharmony_ci if ((g_pipeset & (1 << pipeno)) == 0) 101beacf11bSopenharmony_ci { 102beacf11bSopenharmony_ci g_pipeset |= (1 << pipeno); 103beacf11bSopenharmony_ci ret = pipeno; 104beacf11bSopenharmony_ci break; 105beacf11bSopenharmony_ci } 106beacf11bSopenharmony_ci } 107beacf11bSopenharmony_ci 108beacf11bSopenharmony_ci return ret; 109beacf11bSopenharmony_ci} 110beacf11bSopenharmony_ci 111beacf11bSopenharmony_ci/**************************************************************************** 112beacf11bSopenharmony_ci * Name: pipe_free 113beacf11bSopenharmony_ci ****************************************************************************/ 114beacf11bSopenharmony_ci 115beacf11bSopenharmony_cistatic inline void pipe_free(int pipeno) 116beacf11bSopenharmony_ci{ 117beacf11bSopenharmony_ci int ret; 118beacf11bSopenharmony_ci 119beacf11bSopenharmony_ci ret = sem_wait(&g_pipesem); 120beacf11bSopenharmony_ci if (ret == OK) 121beacf11bSopenharmony_ci { 122beacf11bSopenharmony_ci g_pipeset &= ~(1 << pipeno); 123beacf11bSopenharmony_ci (void)sem_post(&g_pipesem); 124beacf11bSopenharmony_ci } 125beacf11bSopenharmony_ci} 126beacf11bSopenharmony_ci 127beacf11bSopenharmony_ci/**************************************************************************** 128beacf11bSopenharmony_ci * Name: pipe_close 129beacf11bSopenharmony_ci ****************************************************************************/ 130beacf11bSopenharmony_ci 131beacf11bSopenharmony_cistatic int pipe_close(struct file *filep) 132beacf11bSopenharmony_ci{ 133beacf11bSopenharmony_ci struct Vnode *vnode = filep->f_vnode; 134beacf11bSopenharmony_ci struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv; 135beacf11bSopenharmony_ci int ret; 136beacf11bSopenharmony_ci 137beacf11bSopenharmony_ci if (dev == NULL) 138beacf11bSopenharmony_ci { 139beacf11bSopenharmony_ci return -EINVAL; 140beacf11bSopenharmony_ci } 141beacf11bSopenharmony_ci 142beacf11bSopenharmony_ci /* Perform common close operations */ 143beacf11bSopenharmony_ci 144beacf11bSopenharmony_ci ret = pipecommon_close(filep); 145beacf11bSopenharmony_ci if (ret == 0 && vnode->useCount <= 1) 146beacf11bSopenharmony_ci { 147beacf11bSopenharmony_ci /* Release the pipe when there are no further open references to it. */ 148beacf11bSopenharmony_ci 149beacf11bSopenharmony_ci pipe_free(dev->d_pipeno); 150beacf11bSopenharmony_ci } 151beacf11bSopenharmony_ci 152beacf11bSopenharmony_ci return ret; 153beacf11bSopenharmony_ci} 154beacf11bSopenharmony_ci 155beacf11bSopenharmony_ci/**************************************************************************** 156beacf11bSopenharmony_ci * Name: pipe_unlink 157beacf11bSopenharmony_ci ****************************************************************************/ 158beacf11bSopenharmony_ci 159beacf11bSopenharmony_ci#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS 160beacf11bSopenharmony_ci int pipe_unlink(struct Vnode *vnode) 161beacf11bSopenharmony_ci{ 162beacf11bSopenharmony_ci struct pipe_dev_s *dev = ((struct drv_data *)vnode->data)->priv; 163beacf11bSopenharmony_ci uint8_t pipeno = 0; 164beacf11bSopenharmony_ci int ret; 165beacf11bSopenharmony_ci 166beacf11bSopenharmony_ci if (dev != NULL) 167beacf11bSopenharmony_ci { 168beacf11bSopenharmony_ci pipeno = dev->d_pipeno; 169beacf11bSopenharmony_ci } 170beacf11bSopenharmony_ci /* Perform common close operations */ 171beacf11bSopenharmony_ci ret = pipecommon_unlink(vnode); 172beacf11bSopenharmony_ci if (ret == 0) 173beacf11bSopenharmony_ci { 174beacf11bSopenharmony_ci (void)sem_wait(&g_pipesem); 175beacf11bSopenharmony_ci g_pipecreated &= ~(1 << pipeno); 176beacf11bSopenharmony_ci (void)sem_post(&g_pipesem); 177beacf11bSopenharmony_ci /* Release the pipe when there are no further open references to it. */ 178beacf11bSopenharmony_ci pipe_free(pipeno); 179beacf11bSopenharmony_ci } 180beacf11bSopenharmony_ci return ret; 181beacf11bSopenharmony_ci} 182beacf11bSopenharmony_ci#endif 183beacf11bSopenharmony_ci 184beacf11bSopenharmony_ci/**************************************************************************** 185beacf11bSopenharmony_ci * Public Functions 186beacf11bSopenharmony_ci ****************************************************************************/ 187beacf11bSopenharmony_ci 188beacf11bSopenharmony_ci/**************************************************************************** 189beacf11bSopenharmony_ci * Name: pipe2 190beacf11bSopenharmony_ci * 191beacf11bSopenharmony_ci * Description: 192beacf11bSopenharmony_ci * pipe() creates a pair of file descriptors, pointing to a pipe vnode, 193beacf11bSopenharmony_ci * and places them in the array pointed to by 'fd'. fd[0] is for reading, 194beacf11bSopenharmony_ci * fd[1] is for writing. 195beacf11bSopenharmony_ci * 196beacf11bSopenharmony_ci * NOTE: mkfifo2 is a special, non-standard, NuttX-only interface. Since 197beacf11bSopenharmony_ci * the NuttX FIFOs are based in in-memory, circular buffers, the ability 198beacf11bSopenharmony_ci * to control the size of those buffers is critical for system tuning. 199beacf11bSopenharmony_ci * 200beacf11bSopenharmony_ci * Input Parameters: 201beacf11bSopenharmony_ci * fd[2] - The user provided array in which to catch the pipe file 202beacf11bSopenharmony_ci * descriptors 203beacf11bSopenharmony_ci * bufsize - The size of the in-memory, circular buffer in bytes. 204beacf11bSopenharmony_ci * 205beacf11bSopenharmony_ci * Returned Value: 206beacf11bSopenharmony_ci * 0 is returned on success; otherwise, -1 is returned with errno set 207beacf11bSopenharmony_ci * appropriately. 208beacf11bSopenharmony_ci * 209beacf11bSopenharmony_ci ****************************************************************************/ 210beacf11bSopenharmony_ci 211beacf11bSopenharmony_cistatic void UpdateDev(struct pipe_dev_s *dev) 212beacf11bSopenharmony_ci{ 213beacf11bSopenharmony_ci int ret; 214beacf11bSopenharmony_ci struct Vnode *vnode = NULL; 215beacf11bSopenharmony_ci struct pipe_dev_s *olddev = NULL; 216beacf11bSopenharmony_ci struct drv_data *data = NULL; 217beacf11bSopenharmony_ci 218beacf11bSopenharmony_ci VnodeHold(); 219beacf11bSopenharmony_ci ret = VnodeLookup(dev->name, &vnode, 0); 220beacf11bSopenharmony_ci if (ret != 0) 221beacf11bSopenharmony_ci { 222beacf11bSopenharmony_ci VnodeDrop(); 223beacf11bSopenharmony_ci PRINT_ERR("[%s,%d] failed. err: %d\n", __FUNCTION__, __LINE__, ret); 224beacf11bSopenharmony_ci return; 225beacf11bSopenharmony_ci } 226beacf11bSopenharmony_ci data = (struct drv_data *)vnode->data; 227beacf11bSopenharmony_ci olddev = (struct pipe_dev_s *)data->priv; 228beacf11bSopenharmony_ci if (olddev != NULL) 229beacf11bSopenharmony_ci { 230beacf11bSopenharmony_ci if (olddev->d_buffer != NULL) 231beacf11bSopenharmony_ci { 232beacf11bSopenharmony_ci free(olddev->d_buffer); 233beacf11bSopenharmony_ci olddev->d_buffer = NULL; 234beacf11bSopenharmony_ci } 235beacf11bSopenharmony_ci pipecommon_freedev(olddev); 236beacf11bSopenharmony_ci } 237beacf11bSopenharmony_ci data->priv = dev; 238beacf11bSopenharmony_ci VnodeDrop(); 239beacf11bSopenharmony_ci return; 240beacf11bSopenharmony_ci} 241beacf11bSopenharmony_ci 242beacf11bSopenharmony_ciint pipe(int fd[2]) 243beacf11bSopenharmony_ci{ 244beacf11bSopenharmony_ci struct pipe_dev_s *dev = NULL; 245beacf11bSopenharmony_ci char devname[16]; 246beacf11bSopenharmony_ci int pipeno; 247beacf11bSopenharmony_ci int errcode; 248beacf11bSopenharmony_ci int ret; 249beacf11bSopenharmony_ci struct file *filep = NULL; 250beacf11bSopenharmony_ci size_t bufsize = 1024; 251beacf11bSopenharmony_ci 252beacf11bSopenharmony_ci /* Get exclusive access to the pipe allocation data */ 253beacf11bSopenharmony_ci 254beacf11bSopenharmony_ci ret = sem_wait(&g_pipesem); 255beacf11bSopenharmony_ci if (ret < 0) 256beacf11bSopenharmony_ci { 257beacf11bSopenharmony_ci errcode = -ret; 258beacf11bSopenharmony_ci goto errout; 259beacf11bSopenharmony_ci } 260beacf11bSopenharmony_ci 261beacf11bSopenharmony_ci /* Allocate a minor number for the pipe device */ 262beacf11bSopenharmony_ci 263beacf11bSopenharmony_ci pipeno = pipe_allocate(); 264beacf11bSopenharmony_ci if (pipeno < 0) 265beacf11bSopenharmony_ci { 266beacf11bSopenharmony_ci (void)sem_post(&g_pipesem); 267beacf11bSopenharmony_ci errcode = -pipeno; 268beacf11bSopenharmony_ci goto errout; 269beacf11bSopenharmony_ci } 270beacf11bSopenharmony_ci 271beacf11bSopenharmony_ci /* Create a pathname to the pipe device */ 272beacf11bSopenharmony_ci 273beacf11bSopenharmony_ci snprintf_s(devname, sizeof(devname), sizeof(devname) - 1, "/dev/pipe%d", pipeno); 274beacf11bSopenharmony_ci 275beacf11bSopenharmony_ci /* No.. Allocate and initialize a new device structure instance */ 276beacf11bSopenharmony_ci 277beacf11bSopenharmony_ci dev = pipecommon_allocdev(bufsize, devname); 278beacf11bSopenharmony_ci if (!dev) 279beacf11bSopenharmony_ci { 280beacf11bSopenharmony_ci (void)sem_post(&g_pipesem); 281beacf11bSopenharmony_ci errcode = ENOMEM; 282beacf11bSopenharmony_ci goto errout_with_pipe; 283beacf11bSopenharmony_ci } 284beacf11bSopenharmony_ci 285beacf11bSopenharmony_ci dev->d_pipeno = pipeno; 286beacf11bSopenharmony_ci 287beacf11bSopenharmony_ci /* Check if the pipe device has already been created */ 288beacf11bSopenharmony_ci 289beacf11bSopenharmony_ci if ((g_pipecreated & (1 << pipeno)) == 0) 290beacf11bSopenharmony_ci { 291beacf11bSopenharmony_ci /* Register the pipe device */ 292beacf11bSopenharmony_ci 293beacf11bSopenharmony_ci ret = register_driver(devname, &pipe_fops, 0660, (void *)dev); 294beacf11bSopenharmony_ci if (ret != 0) 295beacf11bSopenharmony_ci { 296beacf11bSopenharmony_ci (void)sem_post(&g_pipesem); 297beacf11bSopenharmony_ci errcode = -ret; 298beacf11bSopenharmony_ci goto errout_with_dev; 299beacf11bSopenharmony_ci } 300beacf11bSopenharmony_ci 301beacf11bSopenharmony_ci /* Remember that we created this device */ 302beacf11bSopenharmony_ci 303beacf11bSopenharmony_ci g_pipecreated |= (1 << pipeno); 304beacf11bSopenharmony_ci } 305beacf11bSopenharmony_ci else 306beacf11bSopenharmony_ci { 307beacf11bSopenharmony_ci UpdateDev(dev); 308beacf11bSopenharmony_ci } 309beacf11bSopenharmony_ci (void)sem_post(&g_pipesem); 310beacf11bSopenharmony_ci 311beacf11bSopenharmony_ci /* Get a write file descriptor */ 312beacf11bSopenharmony_ci 313beacf11bSopenharmony_ci fd[1] = open(devname, O_WRONLY); 314beacf11bSopenharmony_ci if (fd[1] < 0) 315beacf11bSopenharmony_ci { 316beacf11bSopenharmony_ci errcode = -fd[1]; 317beacf11bSopenharmony_ci goto errout_with_driver; 318beacf11bSopenharmony_ci } 319beacf11bSopenharmony_ci 320beacf11bSopenharmony_ci /* Get a read file descriptor */ 321beacf11bSopenharmony_ci 322beacf11bSopenharmony_ci fd[0] = open(devname, O_RDONLY); 323beacf11bSopenharmony_ci if (fd[0] < 0) 324beacf11bSopenharmony_ci { 325beacf11bSopenharmony_ci errcode = -fd[0]; 326beacf11bSopenharmony_ci goto errout_with_wrfd; 327beacf11bSopenharmony_ci } 328beacf11bSopenharmony_ci 329beacf11bSopenharmony_ci ret = fs_getfilep(fd[0], &filep); 330beacf11bSopenharmony_ci filep->ops = &pipe_fops; 331beacf11bSopenharmony_ci 332beacf11bSopenharmony_ci ret = fs_getfilep(fd[1], &filep); 333beacf11bSopenharmony_ci filep->ops = &pipe_fops; 334beacf11bSopenharmony_ci 335beacf11bSopenharmony_ci return OK; 336beacf11bSopenharmony_ci 337beacf11bSopenharmony_cierrout_with_wrfd: 338beacf11bSopenharmony_ci close(fd[1]); 339beacf11bSopenharmony_ci 340beacf11bSopenharmony_cierrout_with_driver: 341beacf11bSopenharmony_ci unregister_driver(devname); 342beacf11bSopenharmony_ci (void)sem_wait(&g_pipesem); 343beacf11bSopenharmony_ci g_pipecreated &= ~(1 << pipeno); 344beacf11bSopenharmony_ci (void)sem_post(&g_pipesem); 345beacf11bSopenharmony_ci 346beacf11bSopenharmony_cierrout_with_dev: 347beacf11bSopenharmony_ci if (dev) 348beacf11bSopenharmony_ci { 349beacf11bSopenharmony_ci pipecommon_freedev(dev); 350beacf11bSopenharmony_ci } 351beacf11bSopenharmony_ci 352beacf11bSopenharmony_cierrout_with_pipe: 353beacf11bSopenharmony_ci pipe_free(pipeno); 354beacf11bSopenharmony_ci 355beacf11bSopenharmony_cierrout: 356beacf11bSopenharmony_ci set_errno(errcode); 357beacf11bSopenharmony_ci return VFS_ERROR; 358beacf11bSopenharmony_ci} 359beacf11bSopenharmony_ci 360beacf11bSopenharmony_ciint pipe_init(void) 361beacf11bSopenharmony_ci{ 362beacf11bSopenharmony_ci int ret = sem_init(&g_pipesem, 0, 1); 363beacf11bSopenharmony_ci if (ret != 0) { 364beacf11bSopenharmony_ci dprintf("pipe_init failed!\n"); 365beacf11bSopenharmony_ci } 366beacf11bSopenharmony_ci return ret; 367beacf11bSopenharmony_ci} 368beacf11bSopenharmony_ci 369beacf11bSopenharmony_ciLOS_MODULE_INIT(pipe_init, LOS_INIT_LEVEL_KMOD_EXTENDED); 370beacf11bSopenharmony_ci 371beacf11bSopenharmony_ci#endif /* CONFIG_DEV_PIPE_SIZE > 0 */ 372