/** * @brief Opens a flink device file * @param file_name: Device file (null terminated array). * @return flink_dev*: Pointer to the opened flink device or NULL in case of error. */ flink_dev* flink_open(const char* file_name) { flink_dev* dev = NULL; // Allocate memory for flink_t dev = malloc(sizeof(flink_dev)); if(dev == NULL) { // allocation failed libc_error(); return NULL; } // Open device file dev->fd = open(file_name, O_RDWR); if(dev->fd < 0) { // failed to open device free(dev); libc_error(); return NULL; } if(get_subdevices(dev) < 0) { // reading subdevices failed close(dev->fd); free(dev); return NULL; } return dev; }
/** * @brief Read header of all subdevices and update flink device. * * @param dev: flink device to update * @return int: number of subdevices read, or -1 in case of error. */ static int get_subdevices(flink_dev* dev) { flink_subdev* subdev = NULL; int i = 0, ret = 0; if(!validate_flink_dev(dev)) { flink_error(FLINK_EINVALDEV); return EXIT_ERROR; } // Read nof subdevices dev->nof_subdevices = read_nof_subdevices(dev); // Allocate memory dev->subdevices = calloc(dev->nof_subdevices, sizeof(flink_subdev)); if(dev->subdevices == NULL) { // allocation failed libc_error(); dev->nof_subdevices = 0; return EXIT_ERROR; } // Fillup all information for(i = 0; i < dev->nof_subdevices; i++) { // for each subdevice subdev = dev->subdevices + i; subdev->id = i; ret = flink_ioctl(dev, READ_SUBDEVICE_INFO, subdev); subdev->parent = dev; } return ret; }
void FileDescriptor::RaiseError(const char* msg) { if (ignoreErrors.size() == 0) { // Ignore none throw libc_error(msg); } ErrorSet * curIgnore = ignoreErrors.back().get(); if (!curIgnore) { // Ignore all return; } if (!curIgnore->count(errno)) { // Don't ignore this one throw libc_error(msg); } }
/** * @brief Select a flink subdevice for further operations. * @param subdev: Subdevice to select. * @param exclusive: Block access to this subdevice for other processes. * @return int: 0 on success, else -1. */ int flink_subdevice_select(flink_subdev* subdev, uint8_t exclusive) { ioctl_cmd_t cmd = SELECT_SUBDEVICE; if(exclusive) cmd = SELECT_SUBDEVICE_EXCL; if(flink_ioctl(subdev->parent, cmd, &(subdev->id)) < 0) { libc_error(); return EXIT_ERROR; } return EXIT_SUCCESS; }
/** * @brief Read number of subdevices from flink device. * * @param dev: Device to read * @return int: Number of flink devices or -1 in case of error. */ static int read_nof_subdevices(flink_dev* dev) { uint8_t n = 0; dbg_print("reading number of subdevices...\n"); if(flink_ioctl(dev, READ_NOF_SUBDEVICES, &n) < 0) { dbg_print(" --> failed!\n"); libc_error(); return EXIT_ERROR; } dbg_print(" --> %u\n", n); return n; }
/** * @brief Reset a flink subdevice. * @param subdev: Subdevice to reset * @return int: 0 on success, else -1. */ int flink_subdevice_reset(flink_subdev* subdev) { uint32_t offset = CONFIG_OFFSET; uint8_t reset = 1; if(!validate_flink_subdev(subdev)) { flink_error(FLINK_EINVALSUBDEV); return EXIT_ERROR; } if(flink_write_bit(subdev, offset, RESET_BIT, &reset)) { libc_error(); return EXIT_ERROR; } return EXIT_SUCCESS; }
/** * @brief Configures a channel as input or output * @param subdev: Subdevice containing the channel. * @param channel: Channel number. * @param output: Value, a value of nonzero configures the channel as output. * @return int: 0 on success, -1 in case of failure. */ int flink_dio_set_direction(flink_subdev* subdev, uint32_t channel, uint8_t output) { uint32_t offset; uint8_t bit; dbg_print("Setting digital I/O direction for channel %d on subdevice %d\n", channel, subdev->id); offset = HEADER_SIZE + SUBHEADER_SIZE + (channel / (REGISTER_WITH * 8)) * REGISTER_WITH; bit = channel % (REGISTER_WITH * 8); dbg_print(" --> calculated offset is 0x%x\n", offset); dbg_print(" --> calculated bit is %u\n", bit); if(flink_write_bit(subdev, offset, bit, &output)) { libc_error(); return EXIT_ERROR; } return EXIT_SUCCESS; }
/** * @brief Reads an input channel * @param subdev: Subdevice containing the channel. * @param channel: Channel number. * @param value: Contains a value of nonzero if the input is set. * @return int: 0 on success, -1 in case of failure. */ int flink_dio_get_value(flink_subdev* subdev, uint32_t channel, uint8_t* value) { uint32_t offset; uint8_t bit; dbg_print("Reading digital input value from channel %d on subdevice %d\n", channel, subdev->id); offset = HEADER_SIZE + SUBHEADER_SIZE + subdev->nof_channels / (REGISTER_WITH * 8) + channel / (REGISTER_WITH * 8); if(subdev->nof_channels % (REGISTER_WITH * 8) != 0) offset += 4; bit = channel % (REGISTER_WITH * 8); dbg_print("[DEBUG] --> calculated offset is 0x%x\n", offset); dbg_print("[DEBUG] --> calculated bit is %u\n", bit); if(flink_read_bit(subdev, offset, bit, value)) { libc_error(); return EXIT_ERROR; } return EXIT_SUCCESS; }
/** * @brief Sets a output channel to a value * @param subdev: Subdevice containing the channel. * @param channel: Channel number. * @param output: A value of nonzero sets the channel. * @return int: 0 on success, -1 in case of failure. */ int flink_dio_set_value(flink_subdev* subdev, uint32_t channel, uint8_t value) { uint32_t offset; uint8_t bit; uint8_t val = (value != 0); dbg_print("Setting digital output value to %u...\n", val); offset = HEADER_SIZE + SUBHEADER_SIZE + subdev->nof_channels / (REGISTER_WITH * 8) + channel / (REGISTER_WITH * 8); if(subdev->nof_channels % (REGISTER_WITH * 8) != 0) offset += 4; bit = channel % (REGISTER_WITH * 8); dbg_print(" --> calculated offset is 0x%x\n", offset); dbg_print(" --> calculated bit is %u\n", bit); if(flink_write_bit(subdev, offset, bit, &val)) { libc_error(); return EXIT_ERROR; } return EXIT_SUCCESS; }