bsdi_ioctl.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 772 行 · 第 1/2 页

C
772
字号
#include "config.h"/* * Hacked version of the linux cdrom.c kernel module - everything except the * DVD handling ripped out and the rest rewritten to use raw SCSI commands * on BSD/OS 4.2 (but should work with earlier versions as well).*/#include <sys/types.h>#include <mplaylib.h>#include <mplaylib.h>#include <errno.h>#include <mplaylib.h>#include <sys/ioctl.h>#include </sys/dev/scsi/scsi.h>#include </sys/dev/scsi/scsi_ioctl.h>#include "bsdi_dvd.h"/* * Now get rid of the override/intercept macro so we can call the real ioctl() * routine!*/#undef	ioctl#define CMD_READ_10             0x28#define CMD_READ_TOC_PMA_ATIP   0x43#define CMD_READ_CD             0xbe#define	CMD_START_STOP_UNIT	0x1b#define	CMD_SEND_KEY		0xa3#define	CMD_REPORT_KEY		0xa4#define	CMD_READ_DVD_STRUCTURE	0xad#undef memcpy#define memcpy uc_memcpy#define copy_key(dest,src)	memcpy((dest), (src), sizeof(dvd_key))#define copy_chal(dest,src)	memcpy((dest), (src), sizeof(dvd_challenge))/* Define the Cdrom Generic Command structure */typedef	struct	cgc		{		u_char	cdb[12];		u_char	*buf;		int	buflen;		int	rw;		int	timeout;		scsi_user_sense_t *sus;		} cgc_t;static int scsi_cmd(int, cgc_t *);static int cdrom_ioctl(int, u_long, void *);static int cdrom_tray_move(int, int);static void cdrom_count_tracks(int, tracktype *);static int dvd_ioctl(int, u_long, void *);static	int	debug = 0;void dvd_cdrom_debug(int flag)	{	debug = flag;	}/* * This is the published entry point.   Actually applications should simply * include <dvd.h> and not refer to this at all.*/int dvd_cdrom_ioctl(int fd, unsigned long cmd, void *arg)	{	switch	(cmd)		{		case	DVD_AUTH:		case	DVD_READ_STRUCT:			return(dvd_ioctl(fd, cmd, arg));		case	CDROMREADTOCHDR:		case	CDROMREADTOCENTRY:		case	CDROMEJECT:		case	CDROMREADRAW:		case	CDROMREADMODE1:		case	CDROMREADMODE2:		case	CDROMCLOSETRAY:		case	CDROM_DRIVE_STATUS:		case	CDROM_DISC_STATUS:			return(cdrom_ioctl(fd, cmd, arg));		default:			return(ioctl(fd, cmd, arg));		}	}static void setup_report_key(cgc_t *cgc, u_int agid, u_int type)	{	cgc->cdb[0] = CMD_REPORT_KEY;	cgc->cdb[10] = type | (agid << 6);	switch	(type)		{		case	0:		case	5:		case	8:			cgc->buflen = 8;			break;		case	1:			cgc->buflen = 16;			break;		case	2:		case	4:			cgc->buflen = 12;			break;		}	cgc->cdb[9] = cgc->buflen;	cgc->rw = SUC_READ;;	}static void setup_send_key(cgc_t *cgc, u_int agid, u_int type)	{	cgc->cdb[0] = CMD_SEND_KEY;	cgc->cdb[10] = type | (agid << 6);	switch	(type)		{		case	1:			cgc->buflen = 16;			break;		case	3:			cgc->buflen = 12;			break;		case	6:			cgc->buflen = 8;			break;		}	cgc->cdb[9] = cgc->buflen;	cgc->rw = SUC_WRITE;	}static void cgc_init(cgc_t *cgc, void *buf, int len, int type)	{	memset(cgc, 0, sizeof (*cgc));	if	(buf)		memset(buf, 0, len);	cgc->buf = (u_char *)buf;	cgc->buflen = len;	cgc->rw = type;	cgc->timeout = 5;	/* 5 second timeout */	}static int dvd_do_auth(int fd, dvd_authinfo *ai)	{	int	ret;	u_char	buf[20];	cgc_t	cgc;	rpc_state_t rpc_state;	memset(buf, 0, sizeof(buf));	cgc_init(&cgc, buf, 0, SUC_READ);	switch	(ai->type)		{		case	DVD_LU_SEND_AGID:	/* LU data send */			setup_report_key(&cgc, ai->lsa.agid, 0);			if	(ret = scsi_cmd(fd, &cgc))				return ret;			ai->lsa.agid = buf[7] >> 6;			break;		case	DVD_LU_SEND_KEY1:			setup_report_key(&cgc, ai->lsk.agid, 2);			if	(ret = scsi_cmd(fd, &cgc))				return ret;			copy_key(ai->lsk.key, &buf[4]);			break;		case	DVD_LU_SEND_CHALLENGE:			setup_report_key(&cgc, ai->lsc.agid, 1);			if	(ret = scsi_cmd(fd, &cgc))				return ret;			copy_chal(ai->lsc.chal, &buf[4]);			break;		case	DVD_LU_SEND_TITLE_KEY:	/* Post-auth key */			setup_report_key(&cgc, ai->lstk.agid, 4);			cgc.cdb[5] = ai->lstk.lba;			cgc.cdb[4] = ai->lstk.lba >> 8;			cgc.cdb[3] = ai->lstk.lba >> 16;			cgc.cdb[2] = ai->lstk.lba >> 24;			if	(ret = scsi_cmd(fd, &cgc))				return ret;			ai->lstk.cpm = (buf[4] >> 7) & 1;			ai->lstk.cp_sec = (buf[4] >> 6) & 1;			ai->lstk.cgms = (buf[4] >> 4) & 3;			copy_key(ai->lstk.title_key, &buf[5]);			break;		case	DVD_LU_SEND_ASF:			setup_report_key(&cgc, ai->lsasf.agid, 5);			if	(ret = scsi_cmd(fd, &cgc))				return ret;			ai->lsasf.asf = buf[7] & 1;			break;		case	DVD_HOST_SEND_CHALLENGE: /* LU data receive (LU changes state) */			setup_send_key(&cgc, ai->hsc.agid, 1);			buf[1] = 0xe;			copy_chal(&buf[4], ai->hsc.chal);			if	(ret = scsi_cmd(fd, &cgc))				return ret;			ai->type = DVD_LU_SEND_KEY1;			break;		case	DVD_HOST_SEND_KEY2:			setup_send_key(&cgc, ai->hsk.agid, 3);			buf[1] = 0xa;			copy_key(&buf[4], ai->hsk.key);			if	(ret = scsi_cmd(fd, &cgc))				{				ai->type = DVD_AUTH_FAILURE;				return ret;				}			ai->type = DVD_AUTH_ESTABLISHED;			break;		case	DVD_INVALIDATE_AGID:			setup_report_key(&cgc, ai->lsa.agid, 0x3f);			if	(ret = scsi_cmd(fd, &cgc))				return ret;			break;		case	DVD_LU_SEND_RPC_STATE:	/* Get region settings */			setup_report_key(&cgc, 0, 8);			memset(&rpc_state, 0, sizeof(rpc_state_t));			cgc.buf = (char *) &rpc_state;			if	(ret = scsi_cmd(fd, &cgc))				{				ai->lrpcs.type = 0;				ai->lrpcs.rpc_scheme = 0;				}			else				{				ai->lrpcs.type = rpc_state.type_code;				ai->lrpcs.vra = rpc_state.vra;				ai->lrpcs.ucca = rpc_state.ucca;				ai->lrpcs.region_mask = rpc_state.region_mask;				ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;				}			break;		case	DVD_HOST_SEND_RPC_STATE:  /* Set region settings */			setup_send_key(&cgc, 0, 6);			buf[1] = 6;			buf[4] = ai->hrpcs.pdrc;			if	(ret = scsi_cmd(fd, &cgc))				return ret;			break;		default:			return EINVAL;		}	return 0;	}static int dvd_read_physical(int fd, dvd_struct *s)	{	int ret, i;	u_char buf[4 + 4 * 20], *base;	struct dvd_layer *layer;	cgc_t cgc;	cgc_init(&cgc, buf, sizeof(buf), SUC_READ);	cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;	cgc.cdb[6] = s->physical.layer_num;	cgc.cdb[7] = s->type;	cgc.cdb[9] = cgc.buflen & 0xff;	if	(ret = scsi_cmd(fd, &cgc))		return ret;	base = &buf[4];	layer = &s->physical.layer[0];	/* place the data... really ugly, but at least we won't have to	   worry about endianess in userspace or here. */	for	(i = 0; i < 4; ++i, base += 20, ++layer)		{		memset(layer, 0, sizeof(*layer));		layer->book_version = base[0] & 0xf;		layer->book_type = base[0] >> 4;		layer->min_rate = base[1] & 0xf;		layer->disc_size = base[1] >> 4;		layer->layer_type = base[2] & 0xf;		layer->track_path = (base[2] >> 4) & 1;		layer->nlayers = (base[2] >> 5) & 3;		layer->track_density = base[3] & 0xf;		layer->linear_density = base[3] >> 4;		layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];		layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];		layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];		layer->bca = base[16] >> 7;		}	return 0;	}static int dvd_read_copyright(int fd, dvd_struct *s)	{	int ret;	u_char buf[8];	cgc_t cgc;	cgc_init(&cgc, buf, sizeof(buf), SUC_READ);	cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;	cgc.cdb[6] = s->copyright.layer_num;	cgc.cdb[7] = s->type;	cgc.cdb[8] = cgc.buflen >> 8;	cgc.cdb[9] = cgc.buflen & 0xff;	if	(ret = scsi_cmd(fd, &cgc))		return ret;	s->copyright.cpst = buf[4];	s->copyright.rmi = buf[5];	return 0;	}static int dvd_read_disckey(int fd, dvd_struct *s)	{	int ret, size;	u_char *buf;	cgc_t cgc;	size = sizeof(s->disckey.value) + 4;	if	((buf = (u_char *) malloc(size)) == NULL)		return ENOMEM;	cgc_init(&cgc, buf, size, SUC_READ);	cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;	cgc.cdb[7] = s->type;	cgc.cdb[8] = size >> 8;	cgc.cdb[9] = size & 0xff;	cgc.cdb[10] = s->disckey.agid << 6;	if	(!(ret = scsi_cmd(fd, &cgc)))		memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));	free(buf);	return ret;	}static int dvd_read_bca(int fd, dvd_struct *s)	{	int ret;	u_char buf[4 + 188];	cgc_t cgc;	cgc_init(&cgc, buf, sizeof(buf), SUC_READ);	cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;	cgc.cdb[7] = s->type;	cgc.cdb[9] = cgc.buflen = 0xff;	if	(ret = scsi_cmd(fd, &cgc))		return ret;	s->bca.len = buf[0] << 8 | buf[1];	if	(s->bca.len < 12 || s->bca.len > 188)		return EIO;	memcpy(s->bca.value, &buf[4], s->bca.len);	return 0;	}static int dvd_read_manufact(int fd, dvd_struct *s)	{	int ret = 0, size;	u_char *buf;	cgc_t cgc;	size = sizeof(s->manufact.value) + 4;	if	((buf = (u_char *) malloc(size)) == NULL)		return ENOMEM;	cgc_init(&cgc, buf, size, SUC_READ);	cgc.cdb[0] = CMD_READ_DVD_STRUCTURE;	cgc.cdb[7] = s->type;	cgc.cdb[8] = size >> 8;	cgc.cdb[9] = size & 0xff;	if	(ret = scsi_cmd(fd, &cgc))		{		free(buf);		return ret;		}	s->manufact.len = buf[0] << 8 | buf[1];	if	(s->manufact.len < 0 || s->manufact.len > 2048)		ret = -EIO;	else		memcpy(s->manufact.value, &buf[4], s->manufact.len);	free(buf);	return ret;	}static int dvd_read_struct(int fd, dvd_struct *s)	{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?