/*! Set the arg "key" with "value" in the source device. Currently "source" and "access-mode" are valid keys. "source" sets the source device in I/O operations "access-mode" sets the the method of CD access DRIVER_OP_SUCCESS is returned if no error was found, and nonzero if there as an error. */ static driver_return_code_t set_arg_freebsd (void *p_user_data, const char key[], const char value[]) { _img_private_t *p_env = p_user_data; if (!strcmp (key, "source")) { if (!value) return DRIVER_OP_ERROR; free (p_env->gen.source_name); p_env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { p_env->access_mode = str_to_access_mode_freebsd(value); if (p_env->access_mode == _AM_CAM && !p_env->b_cam_init) return init_freebsd_cam(p_env) ? DRIVER_OP_SUCCESS : DRIVER_OP_ERROR; } else return DRIVER_OP_ERROR; return DRIVER_OP_SUCCESS; }
/*! Initialization routine. This is the only thing that doesn't get called via a function pointer. In fact *we* are the ones to set that up. */ CdIo * cdio_open_am_freebsd (const char *psz_orig_source_name, const char *psz_access_mode) { #ifdef HAVE_FREEBSD_CDROM CdIo *ret; _img_private_t *_data; char *psz_source_name; int open_access_mode; /* Access mode passed to cdio_generic_init. */ cdio_funcs_t _funcs = { .audio_get_volume = audio_get_volume_freebsd, .audio_pause = audio_pause_freebsd, .audio_play_msf = audio_play_msf_freebsd, .audio_play_track_index = audio_play_track_index_freebsd, .audio_read_subchannel = audio_read_subchannel_freebsd, .audio_resume = audio_resume_freebsd, .audio_set_volume = audio_set_volume_freebsd, .audio_stop = audio_stop_freebsd, .eject_media = eject_media_freebsd, .free = free_freebsd, .get_arg = get_arg_freebsd, .get_blocksize = get_blocksize_mmc, .get_cdtext = get_cdtext_generic, .get_cdtext_raw = read_cdtext_generic, .get_default_device = cdio_get_default_device_freebsd, .get_devices = cdio_get_devices_freebsd, .get_disc_last_lsn = get_disc_last_lsn_freebsd, .get_discmode = get_discmode_generic, .get_drive_cap = get_drive_cap_freebsd, .get_first_track_num = get_first_track_num_generic, .get_media_changed = get_media_changed_freebsd, .get_mcn = get_mcn_freebsd, .get_num_tracks = get_num_tracks_generic, .get_track_channels = get_track_channels_generic, .get_track_copy_permit = get_track_copy_permit_generic, .get_track_format = get_track_format_freebsd, .get_track_green = get_track_green_freebsd, .get_track_lba = get_track_lba_freebsd, .get_track_preemphasis = get_track_preemphasis_generic, .get_track_msf = NULL, .get_track_isrc = get_track_isrc_freebsd, .lseek = cdio_generic_lseek, .read = cdio_generic_read, .read_audio_sectors = read_audio_sectors_freebsd, .read_data_sectors = read_data_sectors_mmc, .read_mode2_sector = read_mode2_sector_freebsd, .read_mode2_sectors = read_mode2_sectors_freebsd, .read_toc = read_toc_freebsd, .run_mmc_cmd = run_mmc_cmd_freebsd, .set_arg = set_arg_freebsd, .set_blocksize = set_blocksize_mmc, .set_speed = set_speed_freebsd, }; if (!psz_access_mode) psz_access_mode = get_access_mode(psz_orig_source_name); _data = calloc(1, sizeof (_img_private_t)); _data->access_mode = str_to_access_mode_freebsd(psz_access_mode); _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source_name) { psz_source_name=cdio_get_default_device_freebsd(); if (NULL == psz_source_name) { cdio_generic_free (_data); return NULL; } _data->device = psz_source_name; set_arg_freebsd(_data, "source", psz_source_name); } else { if (cdio_is_device_generic(psz_orig_source_name)) { set_arg_freebsd(_data, "source", psz_orig_source_name); _data->device = strdup(psz_orig_source_name); } else { /* The below would be okay if all device drivers worked this way. */ #if 0 cdio_info ("source %s is a not a device", psz_orig_source_name); #endif cdio_generic_free (_data); return NULL; } } ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) { cdio_generic_free (_data); return NULL; } open_access_mode = 0; if (_AM_MMC_RDWR == _data->access_mode) { open_access_mode |= O_RDWR; } else if (_AM_MMC_RDWR_EXCL == _data->access_mode) { open_access_mode |= O_RDWR; } else { open_access_mode |= O_RDONLY; } /* fprintf(stderr, "libcdio_DEBUG: am = %d (MMC_RDWR_EXCL = %d), open = %d (O_RDWR = %d)\n", _data->access_mode, _AM_MMC_RDWR_EXCL, open_access_mode, O_RDWR); */ if (cdio_generic_init(_data, open_access_mode)) { if (_AM_MMC_RDWR_EXCL == _data->access_mode) { int os_errno, pass_dev_no = -1, flock_fd = -1, lock_result; char msg[4096]; lock_result = freebsd_dev_lock(_data->gen.fd, _data->gen.source_name, &os_errno, &pass_dev_no, &flock_fd, msg, 0); if (lock_result <= 0) { cdio_warn ("%s", msg); goto err_exit; } /* One should rather keep this fd open until _data->gen.fd gets closed. It eventually locks a device sibling of _data->gen.source_name. */ if (flock_fd > 0) close(flock_fd); } if ( _data->access_mode == _AM_IOCTL ) { return ret; } else { if (init_freebsd_cam(_data)) return ret; } } err_exit: free(ret); cdio_generic_free(_data); return NULL; #else return NULL; #endif /* HAVE_FREEBSD_CDROM */ }
/*! Initialization routine. This is the only thing that doesn't get called via a function pointer. In fact *we* are the ones to set that up. */ CdIo * cdio_open_am_freebsd (const char *psz_orig_source_name, const char *psz_access_mode) { #ifdef HAVE_FREEBSD_CDROM CdIo *ret; _img_private_t *_data; char *psz_source_name; if (!psz_access_mode) psz_access_mode = get_access_mode(psz_orig_source_name); cdio_funcs_t _funcs = { .audio_get_volume = audio_get_volume_freebsd, .audio_pause = audio_pause_freebsd, .audio_play_msf = audio_play_msf_freebsd, .audio_play_track_index = audio_play_track_index_freebsd, .audio_read_subchannel = audio_read_subchannel_freebsd, .audio_resume = audio_resume_freebsd, .audio_set_volume = audio_set_volume_freebsd, .audio_stop = audio_stop_freebsd, .eject_media = eject_media_freebsd, .free = free_freebsd, .get_arg = get_arg_freebsd, .get_blocksize = get_blocksize_mmc, .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_freebsd, .get_devices = cdio_get_devices_freebsd, .get_disc_last_lsn = get_disc_last_lsn_freebsd, .get_discmode = get_discmode_generic, .get_drive_cap = get_drive_cap_freebsd, .get_first_track_num = get_first_track_num_generic, .get_media_changed = get_media_changed_freebsd, .get_mcn = get_mcn_freebsd, .get_num_tracks = get_num_tracks_generic, .get_track_channels = get_track_channels_generic, .get_track_copy_permit = get_track_copy_permit_generic, .get_track_format = get_track_format_freebsd, .get_track_green = get_track_green_freebsd, .get_track_lba = get_track_lba_freebsd, .get_track_preemphasis = get_track_preemphasis_generic, .get_track_msf = NULL, .lseek = cdio_generic_lseek, .read = cdio_generic_read, .read_audio_sectors = read_audio_sectors_freebsd, .read_data_sectors = read_data_sectors_mmc, .read_mode2_sector = read_mode2_sector_freebsd, .read_mode2_sectors = read_mode2_sectors_freebsd, .read_toc = read_toc_freebsd, .run_mmc_cmd = run_mmc_cmd_freebsd, .set_arg = set_arg_freebsd, .set_blocksize = set_blocksize_mmc, .set_speed = set_speed_freebsd, }; _data = calloc(1, sizeof (_img_private_t)); _data->access_mode = str_to_access_mode_freebsd(psz_access_mode); _data->gen.init = false; _data->gen.fd = -1; _data->gen.toc_init = false; _data->gen.b_cdtext_init = false; _data->gen.b_cdtext_error = false; if (NULL == psz_orig_source_name) { psz_source_name=cdio_get_default_device_freebsd(); if (NULL == psz_source_name) return NULL; _data->device = psz_source_name; set_arg_freebsd(_data, "source", psz_source_name); } else { if (cdio_is_device_generic(psz_orig_source_name)) { set_arg_freebsd(_data, "source", psz_orig_source_name); _data->device = strdup(psz_orig_source_name); } else { /* The below would be okay if all device drivers worked this way. */ #if 0 cdio_info ("source %s is a not a device", psz_orig_source_name); #endif free(_data); return NULL; } } ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) return NULL; if (cdio_generic_init(_data, O_RDONLY)) if ( _data->access_mode == _AM_IOCTL ) { return ret; } else { if (init_freebsd_cam(_data)) return ret; else { cdio_generic_free (_data); return NULL; } } else { cdio_generic_free (_data); return NULL; } #else return NULL; #endif /* HAVE_FREEBSD_CDROM */ }