コード例 #1
0
ファイル: dev_rmscsi.c プロジェクト: andreiw/polaris
/*
 * XXX: a bug still exists here.  we have a thread polling on this
 * XXX: device in the kernel, we need to get rid of this also.
 * XXX: since we're going to move the waiter thread up to the
 * XXX: user level, it'll be easier to kill off as part of the
 * XXX: cleanup of the device private data.
 */
static void
rmscsi_close(char *path, dev_t rdev)
{
	char			namebuf[MAXNAMELEN];
	struct	stat		sb;
	struct devs		*dp;
	struct rmscsi_priv	*rsp;
	int			i;

	debug(1, "rmscsi_close %s\n", path);

	(void) sprintf(namebuf, RMSCSI_NAMEPROTO, path, RMSCSI_BASEPART);
	if (stat(namebuf, &sb) < 0) {
		if (rdev == NODEV) {
			warning(gettext("rmscsi_close: %s; %m\n"), namebuf);
			return;
		}
	} else {
		rdev = sb.st_rdev;
	}

	if ((dp = dev_getdp(rdev)) == NULL) {
		debug(1, "rmscsi_close: %s not in use\n", path);
		return;
	}

	/* get our private data */
	rsp = (struct rmscsi_priv *)dp->dp_priv;

	/*
	 * take care of the listner thread
	 */
	(void) mutex_lock(&rsp->rs_killmutex);
	(void) thr_kill(rsp->rs_tid, SIGUSR1);
	(void) mutex_unlock(&rsp->rs_killmutex);
	(void) thr_join(rsp->rs_tid, 0, 0);
	debug(1, "rmscsi_close: thread id %d reaped (killed/joined)\n",
	    rsp->rs_tid);

	/*
	 * if there is a volume inserted in this device ...
	 */
	if (dp->dp_vol) {
		/*
		 * clean up the name space and the device maps
		 * to remove references to any volume that might
		 * be in the device right now
		 *
		 * this crap with the flags is to keep the
		 * "poll" from being relaunched by this function
		 *
		 * yes, its a hack and there should be a better way
		 */
		if (dp->dp_dsw->d_flags & D_POLL) {
			dp->dp_dsw->d_flags &= ~D_POLL;
			dev_eject(dp->dp_vol, TRUE);
			dp->dp_dsw->d_flags |= D_POLL;
		} else {
			dev_eject(dp->dp_vol, TRUE);
		}
		if (dp->dp_vol != NULL) {
			return;
		}
		/* do the eject work */
		(void) ioctl(rsp->rs_fd[RMSCSI_BASEPART], DKIOCEJECT, 0);
	}

	/*
	 * clean up the names in the name space
	 */
	node_unlink(dp->dp_bvn);
	node_unlink(dp->dp_rvn);

	/*
	 * free the private data we've allocated
	 */
	for (i = 0; i < V_NUMPAR; i++) {
		if (rsp->rs_rawpath[i]) {
			free(rsp->rs_rawpath[i]);
		}
		if (rsp->rs_fd[i] != -1) {
			(void) close(rsp->rs_fd[i]);
		}
	}
#if defined(_FIRMWARE_NEEDS_FDISK)
	for (i = 0; i < (FD_NUMPART+1); i++) {
		if (rsp->rs_raw_pfd[i] >= 0) {
			(void) close(rsp->rs_raw_pfd[i]);
		}
	}
#endif
	free(rsp);

	/*
	 * free the dp, so no one points at us anymore
	 */
	dev_freedp(dp);
}
コード例 #2
0
ファイル: main.c プロジェクト: tsmetana/majacd
int main(int argc, char **argv)
{
#define IOCTL_ERROR(__str) \
	do { \
		msg(MSG_ERR, "%s: Error during ioctl call\n", __str);\
		dev_close();\
		cd_device = NULL;\
		is_error = TRUE;\
	} while (0)

	int opt;
	int opt_index;
	int tracklist = -1;
	static struct option options[] = {
		{"help", 0, 0, 'h'},
		{"version", 0, 0, 'V'},
		{"device", 1, 0, 'd'},
		{"noscan", 0, 0, 'n'},
		{"slave", 0, 0, 's'},
		{0, 0, 0, 0}
	};
	char *cmd_str = NULL;
	size_t line_len;
	char *cmd_ptr = NULL;
	command_t cmd;
	char *cd_device = NULL;
	char *tmp_device = NULL;
	char **device_list = NULL;
	int num_devices = 0;
	unsigned short slave = 0;
	int arg_val;
	int noscan = 0;
	int i;
	int is_error = FALSE;
	dev_status_t status;
	
	while ((opt = getopt_long(argc, argv, "hvVd:ns",
			options, &opt_index)) != -1) {
		switch (opt) {
			case 'h':
				msg(MSG_STD, "help not implemented yet... sorry\n");
				exit(0);
				break;
			case 'V':
				msg(MSG_STD, "Maja's CD player, version " VERSION "\n");
				exit(0);
				break;
			case 'd':
				cd_device = optarg;
				break;
			case 'n':
				noscan = 1;
				break;
			case 's':
				slave = 1;
				break;
			default:
				break;
		}
	}
	if ((!cd_device) && (noscan) && (!slave)) {
		msg(MSG_ERR, "No device specified and scanning prohibited. "
				"Don't know what to do.\nExiting.\n\n");
		return EXIT_FAILURE;
	}
	if (cd_device) {
		if (dev_open(cd_device) < 0) {
			msg(MSG_ERR, "Error opening device %s\n", cd_device);
			return EXIT_FAILURE;
		}
		dev_prepare();
		if (!dev_isaudio()) {
			msg(MSG_STD, "%s: no audio disc\n", cd_device);
			dev_close();
			cd_device = NULL;
			is_error = TRUE;
		}
	}
	
	num_devices = get_cd_devices(&device_list);
	if (!cd_device && !noscan && !is_error) {
		msg(MSG_STD, "Scanning devices...\n");
		for (i = 0; i < num_devices; i++) {
			cd_device = device_list[i];
			if (dev_open(cd_device) < 0)
				msg(MSG_STD, "%s: could not open", cd_device);
			dev_prepare();
			if (dev_isaudio()) {
				msg(MSG_STD, "%s: OK\n", cd_device);
				break;
			} else
				msg(MSG_STD, "%s: no audio disc\n", cd_device);
			dev_close();
			cd_device = NULL;
		}
	}
	if ((!cd_device) && (!slave)) {
		msg(MSG_ERR, "No usable CD device found.\n");
		free_list(&device_list, num_devices);
		return EXIT_FAILURE;
	}
	if (slave) {
		msg(MSG_STD, is_error ? "ERROR\n" : "OK\n");
	}
	if (optind == argc) {
		if (!slave) {
			msg(MSG_STD, "No command given\n");
			free_list(&device_list, num_devices);
			return EXIT_FAILURE;
		}
	} else if (argv[optind])
		cmd_str = strdup(argv[optind]);
	
	do {
		is_error = FALSE;
		if ((!cmd_str) && (slave)) {
			if (getline(&cmd_str, &line_len, stdin) < 0) {
				free(cmd_str);
				cmd_str = strdup("quit");
			}
			if ((cmd_ptr = strrchr(cmd_str, '\n')))
				*cmd_ptr = '\0';
		}
		if ((!cd_device)
				&& (strncmp(cmd_str, "device", 6) != 0)
				&& (strcmp(cmd_str, "scan") != 0)
				&& (strcmp(cmd_str, "quit") != 0)) {
			msg(MSG_STD, "No device opened. "
					"Only 'scan', 'device' and 'quit' commands are allowed\n");
			msg(MSG_STD, "ERROR\n");
			free(cmd_str);
			cmd_str = NULL;
			continue;
		}
		switch (cmd = get_cmd_num(cmd_str)) {
			case CMD_PLAY:
				arg_val = -1;
				if (++optind < argc)
					arg_val = atoi(argv[optind]);
				cmd_ptr = &(cmd_str[4]);
				while (*cmd_ptr == ' ')
					cmd_ptr++;
				if ((arg_val < 0) && (*cmd_ptr != '\0'))
					arg_val = atoi(cmd_ptr);
				if (arg_val <= 0)
					arg_val = 1;
				if (dev_query_status(&status, &tracklist, NULL, NULL) < 0)
					IOCTL_ERROR("Play");
				else {
					if ((status != ST_PLAYING) || (arg_val != tracklist)) {
						STATUS_OUT(cd_device, arg_val, "Playing", 0U, 0U);
						if (dev_play(arg_val) < 0)
							IOCTL_ERROR("Play");
					} else
						if (print_status(cd_device) < 0)
							IOCTL_ERROR("Play");
					tracklist = -1;
				}
				break;
			case CMD_STOP:
				if (dev_stop() < 0)
					IOCTL_ERROR("Stop");
				break;
			case CMD_PAUSE:
				if (dev_pause() < 0)
					IOCTL_ERROR("Pause");
				break;
			case CMD_NEXT:
				if ((dev_query_status(NULL, &tracklist, NULL, NULL) < 0) ||
						(dev_stop < 0) || (dev_play(tracklist + 1) < 0))
					IOCTL_ERROR("Next");
				break;
			case CMD_PREV:
				if ((dev_query_status(NULL, &tracklist, NULL, NULL) < 0) ||
						(dev_stop < 0) || (dev_play(tracklist - 1) < 0))
					IOCTL_ERROR("Prev");
				break;
			case CMD_TOGGLE:
				if ((dev_query_status(&status, NULL, NULL, NULL) < 0) ||
						((status == ST_PLAYING) && (dev_pause() < 0)) ||
						((status == ST_PAUSED) && (dev_resume() < 0)))
					IOCTL_ERROR("Toggle");
				break;
			case CMD_EJECT:
				if (dev_eject() < 0)
					IOCTL_ERROR("Eject");
				break;
			case CMD_CLOSE:
				if (dev_close_tray() < 0)
					IOCTL_ERROR("Close");
				break;
			case CMD_STATUS:
				if (print_status(cd_device) < 0)
					IOCTL_ERROR("Status");
				break;
			case CMD_INFO:
				if (print_info(cd_device) < 0)
					is_error = TRUE;
				break;
			case CMD_SCAN:
				dev_close();
				for (i = 0; i < num_devices; i++) {
					tmp_device = device_list[i];
					if (dev_open(tmp_device) < 0) {
						msg(MSG_STD, "%s: could not open\n", tmp_device);
						msg(MSG_STD, "ERROR\n");
						is_error = TRUE;
						continue;
					}
					dev_prepare();
					if (dev_isaudio())
						msg(MSG_STD, "%s: OK\n", tmp_device);
					else
						msg(MSG_STD, "%s: no audio disc\n", tmp_device);
					dev_close();
				}
				if (cd_device) {
					if (dev_open(cd_device) < 0) {
						msg(MSG_STD, "%s: error reopening\n", cd_device);
						is_error = TRUE;
					} else
						dev_prepare();
				}
				break;
			case CMD_DEVICE:
				cmd_ptr = &(cmd_str[6]);
				while (*cmd_ptr == ' ')
					++cmd_ptr;
				is_error = TRUE;
				if (*cmd_ptr == '\0') {
					for(i = 0; i < num_devices; i++)
						msg(MSG_STD, "%s\n", device_list[i]);
					is_error = FALSE;
				} else {
					dev_close();
					for (i = 0; i < num_devices; i++) {
						if(strcmp(cmd_ptr, device_list[i]) != 0)
							continue;
						tmp_device = device_list[i];
						if (dev_open(tmp_device) < 0) {
							msg(MSG_STD, "%s: could not open\n", tmp_device);
							msg(MSG_STD, "ERROR\n");
						} else {
							dev_prepare();
							if (!dev_isaudio())
								msg(MSG_STD, "%s: no audio disc\n",
										tmp_device);
							else {
								msg(MSG_STD, "%s: OK\n", tmp_device);
								cd_device = device_list[i];
								is_error = FALSE;
							}
						}
						break;
					}
					if ((is_error) && (cd_device)) {
						if (dev_open(cd_device) < 0)
							msg(MSG_STD, "%s: error reopening\n", tmp_device);
						else
							dev_prepare();
					}
				}
				break;
			case CMD_VOLUME:
				cmd_ptr = &(cmd_str[6]);
				while (*cmd_ptr == ' ')
					cmd_ptr++;
				switch (*cmd_ptr) {
					case '+':
						arg_val = dev_get_volume();
						cmd_ptr++;
						arg_val = CLAMP(arg_val + atoi(cmd_ptr), VOL_MIN, VOL_MAX);
						break;
					case '-':
						arg_val = dev_get_volume();
						cmd_ptr++;
						arg_val = CLAMP(arg_val - atoi(cmd_ptr), VOL_MIN, VOL_MAX);
						break;
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
						arg_val = CLAMP(atoi(cmd_ptr), VOL_MIN, VOL_MAX);
						break;
					default:
						arg_val = -1;
						break;
				}
				if ((arg_val >= 0) && (dev_set_volume(arg_val) < 0))
					IOCTL_ERROR("Volume");
				else {
					arg_val = dev_get_volume();
					msg(MSG_STD, "Volume %d\n", arg_val);
				}
				break;
			case CMD_SEEK: {
				unsigned min, sec, st_min, st_sec;
				int trk;

				is_error = (dev_query_status(NULL, &trk, &min, &sec) < 0);
				if (!is_error)
					is_error =
						(dev_get_track_time(trk, &st_min, &st_sec, NULL, NULL) < 0);
				if (is_error) {
					msg(MSG_ERR, "Error querying current position\n");
					break;
				}
				if (!slave && ++optind < argc)
					cmd_ptr = argv[optind];
				else {
					cmd_ptr = &(cmd_str[4]);
					while (*cmd_ptr == ' ')
						cmd_ptr++;
				}
				/* Current position from beginning of the CD in seconds */
				arg_val = (int)((min + st_min) * 60 + st_sec + sec);
				switch (*cmd_ptr) {
					case '+':
						cmd_ptr++;
						arg_val += atoi(cmd_ptr);
						break;
					case '-':
						cmd_ptr++;
						arg_val -= atoi(cmd_ptr);
						break;
					case '0':
					case '1':
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
						arg_val = atoi(cmd_ptr);
						break;
					default:
						arg_val = -1;
						break;
				}
				msg(MSG_STD, "Seeking to: %d\n", arg_val);
				if (dev_seek(arg_val) < 0) {
					msg(MSG_ERR, "Error seeking to %d sec\n", arg_val);
					is_error = TRUE;
				}
				break;
			}
			case CMD_QUIT:
				noscan = 1;
				slave = 0;
				if ((cd_device) && (dev_close() < 0)) {
					msg(MSG_ERR, "Error closing device %s\n", cd_device);
					is_error = TRUE;
				}
				break;
			default:
				if (cmd_str) {
					msg(MSG_ERR, "Unknown command: %s\n", cmd_str);
					is_error = TRUE;
				} else {
					msg(MSG_ERR, "Nothing to do\n");
					is_error = TRUE;
				}
		} /* switch */
		msg(MSG_STD, is_error ? "ERROR\n" : "OK\n");
		fflush(stderr);
		
		free(cmd_str);
		cmd_str = NULL;
	} while (slave);
	
	free_list(&device_list, num_devices);

	return EXIT_SUCCESS;
}