예제 #1
0
AP_HAL::OwnPtr<AP_HAL::I2CDevice>
I2CDeviceManager::get_device(uint8_t bus, uint8_t address)
{
    for (uint8_t i = 0, n = _buses.size(); i < n; i++) {
        if (_buses[i]->bus == bus) {
            return _create_device(*_buses[i], address);
        }
    }

    /* Bus not found for this device, create a new one */
    AP_HAL::OwnPtr<I2CBus> b{new I2CBus()};
    if (!b) {
        return nullptr;
    }

    if (b->open(bus) < 0) {
        return nullptr;
    }

    auto dev = _create_device(*b, address);
    if (!dev) {
        return nullptr;
    }

    _buses.push_back(b.leak());

    return dev;
}
예제 #2
0
AP_HAL::OwnPtr<AP_HAL::SPIDevice>
SPIDeviceManager::get_device(const char *name)
{
    SPIDesc *desc = nullptr;

    /* Find the bus description in the table */
    for (uint8_t i = 0; i < _n_device_desc; i++) {
        if (!strcmp(_device[i].name, name)) {
            desc = &_device[i];
            break;
        }
    }

    if (!desc) {
        printf("SPI: Invalid device name: %s\n", name);
        return AP_HAL::OwnPtr<AP_HAL::SPIDevice>(nullptr);
    }

    /* Find if bus is already open */
    for (uint8_t i = 0, n = _buses.size(); i < n; i++) {
        if (_buses[i]->bus == desc->bus &&
            _buses[i]->kernel_cs == desc->subdev) {
            return _create_device(*_buses[i], *desc);
        }
    }

    /* Bus not found for this device, create a new one */
    AP_HAL::OwnPtr<SPIBus> b{new SPIBus()};
    if (!b || b->open(desc->bus, desc->subdev) < 0) {
        return nullptr;
    }

    auto dev = _create_device(*b, *desc);
    if (!dev) {
        return nullptr;
    }

    _buses.push_back(b.leak());

    return dev;
}
예제 #3
0
파일: audio_out.c 프로젝트: Illius/libao
/* Open a device.  If this is a live device, file == NULL. */
static ao_device* _open_device(int driver_id, ao_sample_format *format,
                   ao_option *options, FILE *file)
{
    ao_functions *funcs;
    driver_list *driver;
    ao_device *device=NULL;
    int result;
        ao_sample_format sformat=*format;
        sformat.matrix=NULL;

    /* Get driver id */
    if ( (driver = _get_driver(driver_id)) == NULL ) {
        errno = AO_ENODRIVER;
        goto error;
    }

    funcs = driver->functions;

    /* Check the driver type */
    if (file == NULL &&
        funcs->driver_info()->type != AO_TYPE_LIVE) {

        errno = AO_ENOTLIVE;
        goto error;
    } else if (file != NULL &&
           funcs->driver_info()->type != AO_TYPE_FILE) {

        errno = AO_ENOTFILE;
        goto error;
    }

    /* Make a new device structure */
    if ( (device = _create_device(driver_id, driver,
                      format, file)) == NULL ) {
        errno = AO_EFAIL;
        goto error;
    }

    /* Initialize the device memory; get static channel mapping */
    if (!funcs->device_init(device)) {
        errno = AO_EFAIL;
        goto error;
    }

    /* Load options */
        errno = ao_device_load_options(device,ao_global_options);
        if(errno) goto error;
        errno = ao_device_load_options(device,options);
        if(errno) goto error;

        /* also sanitize the format input channel matrix */
        if(format->matrix){
          sformat.matrix = _sanitize_matrix(format->channels, format->matrix, device);
          if(!sformat.matrix)
            awarn("Input channel matrix invalid; ignoring.\n");

          /* special-case handling of 'M'. */
          if(sformat.channels==1 && sformat.matrix && !strcmp(sformat.matrix,"M")){
            free(sformat.matrix);
            sformat.matrix=NULL;
          }
        }

        /* If device init was able to declare a static channel mapping
           mechanism, reconcile it to the input now.  Odd drivers that
           need to communicate with a backend device to determine
           channel mapping strategy can still bypass this mechanism
           entirely.  Also, drivers like ALSA may need to adjust
           strategy depending on what device is successfully opened,
           etc, but this still saves work later. */

        if(device->output_matrix && sformat.matrix){
          switch(device->output_matrix_order){
          case AO_OUTPUT_MATRIX_FIXED:
            /* Backend channel ordering is immutable and unused
               channels must still be sent.  Look for the highest
               channel number we are able to map from the input
               matrix. */
            {
              unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix,
                                                         device->output_matrix,
                                                         &device->input_map);
              int max = _channelmask_maxbit(mask);
              if(max<0){
                aerror("Unable to map any channels from input matrix to output");
                errno = AO_EBADFORMAT;
                goto error;
              }
              device->output_channels = max+1;
              device->output_mask = mask;
              device->inter_matrix = _strdup(device->output_matrix);
            }
            break;

          case AO_OUTPUT_MATRIX_COLLAPSIBLE:
            /* the ordering of channels submitted to the backend is
               fixed, but only the channels in use should be present
               in the audio stream */
            {
              unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix,
                                                         device->output_matrix,
                                                         &device->input_map);
              int channels = _channelmask_bits(mask);
              if(channels<0){
                aerror("Unable to map any channels from input matrix to output");
                errno = AO_EBADFORMAT;
                goto error;
              }
              device->output_channels = channels;
              device->output_mask = mask;
              device->inter_matrix = _channelmask_to_matrix(mask,device->output_matrix);
            }
            break;

          case AO_OUTPUT_MATRIX_PERMUTABLE:
            /* The ordering of channels is freeform.  Only the
               channels in use should be sent, and they may be sent in
               any order.  If possible, leave the input ordering
               unchanged */
            {
              unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix,
                                                         device->output_matrix,
                                                         &device->input_map);
              int channels = _channelmask_bits(mask);
              if(channels<0){
                aerror("Unable to map any channels from input matrix to output");
                errno = AO_EBADFORMAT;
                goto error;
              }
              device->output_channels = channels;
              device->output_mask = mask;
              device->inter_matrix = _matrix_intersect(sformat.matrix,device->output_matrix);
            }
            break;

          default:
            aerror("Driver backend failed to set output ordering.\n");
            errno = AO_EFAIL;
            goto error;
          }

        }else{
          device->output_channels = sformat.channels;
        }

        /* other housekeeping */
        device->input_channels = sformat.channels;
        device->bytewidth = (sformat.bits+7)>>3;
        device->rate = sformat.rate;

    /* Open the device */
    result = funcs->open(device, &sformat);
    if (!result) {
          errno = AO_EOPENDEVICE;
          goto error;
    }

        /* set up permutation based on finalized inter_matrix mapping */
        /* The only way device->output_channels could be zero here is
           if the driver has opted to ouput no channels (eg, the null
           driver). */
        if(sformat.matrix){
          if(!device->inter_matrix){
            awarn("Driver %s does not support automatic channel mapping;\n"
                 "\tRouting only L/R channels to output.\n\n",
                 info_table[device->driver_id]->short_name);
            device->inter_matrix=_strdup("L,R");
          }
          {

            /* walk thorugh the inter matrix, match channels */
            char *op=device->inter_matrix;
            int count=0;
            device->inter_permute = calloc(device->output_channels,sizeof(int));

            adebug("\n");

            while(count<device->output_channels){
              int m=0,mm;
              char *h=op;

              if(*op){
                /* find mnemonic offset of inter channel */
                while(*h && *h!=',')h++;
                while(mnemonics[m]){
                  if(!strncmp(mnemonics[m],op,h-op))
                    break;
                  m++;
                }
                mm=m;

                /* find match in input if any */
                device->inter_permute[count] = _find_channel(m,sformat.matrix);
                if(device->inter_permute[count] == -1 && sformat.channels == 1){
                  device->inter_permute[count] = _find_channel(1,sformat.matrix);
                  mm=1;
                }
              }else
                device->inter_permute[count] = -1;

              /* display resulting mapping for now */
              if(device->inter_permute[count]>=0){
                adebug("input %d (%s)\t -> backend %d (%s)\n",
                       device->inter_permute[count], mnemonics[mm],
                       count,mnemonics[m]);
              }else{
                adebug("             \t    backend %d (%s)\n",
                       count,mnemonics[m]);
              }
              count++;
              op=h;
              if(*h)op++;
            }
            {
              char **inch = _tokenize_matrix(sformat.matrix);
              int i,j;
              int unflag=0;
              for(j=0;j<sformat.channels;j++){
                for(i=0;i<device->output_channels;i++)
                  if(device->inter_permute[i]==j)break;
                if(i==device->output_channels){
                  adebug("input %d (%s)\t -> none\n",
                         j,inch[j]);
                  unflag=1;
                }
              }
              _free_map(inch);
              if(unflag)
                awarn("Some input channels are unmapped and will not be used.\n");
            }
            averbose("\n");

          }
        }

        /* if there's no actual permutation to do, release the permutation vector */
        if(device->inter_permute && device->output_channels == device->input_channels){
          int i;
          for(i=0;i<device->output_channels;i++)
            if(device->inter_permute[i]!=i)break;
          if(i==device->output_channels){
            free(device->inter_permute);
            device->inter_permute=NULL;
          }
        }

    /* Resolve actual driver byte format */
    device->driver_byte_format =
        _real_byte_format(device->driver_byte_format);

    /* Only create swap buffer if needed */
        if (device->bytewidth>1 &&
            device->client_byte_format != device->driver_byte_format){
          adebug("swap buffer required:\n");
          adebug("  machine endianness: %d\n",ao_is_big_endian());
          adebug("  device->client_byte_format:%d\n",device->client_byte_format);
          adebug("  device->driver_byte_format:%d\n",device->driver_byte_format);
        }

    if ( (device->bytewidth>1 &&
              device->client_byte_format != device->driver_byte_format) ||
             device->inter_permute){

          result = _realloc_swap_buffer(device, DEF_SWAP_BUF_SIZE);

          if (!result) {

            if(sformat.matrix)free(sformat.matrix);
            device->funcs->close(device);
            device->funcs->device_clear(device);
            free(device);
            errno = AO_EFAIL;
            return NULL; /* Couldn't alloc swap buffer */
          }
    }

    /* If we made it this far, everything is OK. */
        if(sformat.matrix)free(sformat.matrix);
    return device;

 error:
        {
          int errtemp = errno;
          if(sformat.matrix)
            free(sformat.matrix);
          ao_close(device);
          errno=errtemp;
        }
        return NULL;
}