⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdrom.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return ret;}static int cdrom_media_changed(kdev_t dev){	struct cdrom_device_info *cdi = cdrom_find_device(dev);	/* This talks to the VFS, which doesn't like errors - just 1 or 0.  	 * Returning "0" is always safe (media hasn't been changed). Do that 	 * if the low-level cdrom driver dosn't support media changed. */ 	if (cdi == NULL || cdi->ops->media_changed == NULL)		return 0;	if (!CDROM_CAN(CDC_MEDIA_CHANGED))		return 0;	return media_changed(cdi, 0);}/* badly broken, I know. Is due for a fixup anytime. */void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks){	struct cdrom_tochdr header;	struct cdrom_tocentry entry;	int ret, i;	tracks->data=0;	tracks->audio=0;	tracks->cdi=0;	tracks->xa=0;	tracks->error=0;	cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");         if (!CDROM_CAN(CDC_PLAY_AUDIO)) {                 tracks->error=CDS_NO_INFO;                return;        }        	/* Grab the TOC header so we can see how many tracks there are */	if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) {		if (ret == -ENOMEDIUM)			tracks->error = CDS_NO_DISC;		else			tracks->error = CDS_NO_INFO;		return;	}		/* check what type of tracks are on this disc */	entry.cdte_format = CDROM_MSF;	for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {		entry.cdte_track  = i;		if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {			tracks->error=CDS_NO_INFO;			return;		}			if (entry.cdte_ctrl & CDROM_DATA_TRACK) {		    if (entry.cdte_format == 0x10)			tracks->cdi++;		    else if (entry.cdte_format == 0x20) 			tracks->xa++;		    else			tracks->data++;		} else		    tracks->audio++;		cdinfo(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",		       i, entry.cdte_format, entry.cdte_ctrl);	}		cdinfo(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n", 		header.cdth_trk1, tracks->audio, tracks->data, 		tracks->cdi, tracks->xa);}	/* Requests to the low-level drivers will /always/ be done in the   following format convention:   CDROM_LBA: all data-related requests.   CDROM_MSF: all audio-related requests.   However, a low-level implementation is allowed to refuse this   request, and return information in its own favorite format.   It doesn't make sense /at all/ to ask for a play_audio in LBA   format, or ask for multi-session info in MSF format. However, for   backward compatibility these format requests will be satisfied, but   the requests to the low-level drivers will be sanitized in the more   meaningful format indicated above. */staticvoid sanitize_format(union cdrom_addr *addr,		     u_char * curr, u_char requested){	if (*curr == requested)		return;                 /* nothing to be done! */	if (requested == CDROM_LBA) {		addr->lba = (int) addr->msf.frame +			75 * (addr->msf.second - 2 + 60 * addr->msf.minute);	} else {                        /* CDROM_MSF */		int lba = addr->lba;		addr->msf.frame = lba % 75;		lba /= 75;		lba += 2;		addr->msf.second = lba % 60;		addr->msf.minute = lba / 60;	}	*curr = requested;}void init_cdrom_command(struct cdrom_generic_command *cgc, void *buf, int len,			int type){	memset(cgc, 0, sizeof(struct cdrom_generic_command));	if (buf)		memset(buf, 0, len);	cgc->buffer = (char *) buf;	cgc->buflen = len;	cgc->data_direction = type;	cgc->timeout = 5*HZ;}/* DVD handling */#define copy_key(dest,src)	memcpy((dest), (src), sizeof(dvd_key))#define copy_chal(dest,src)	memcpy((dest), (src), sizeof(dvd_challenge))static void setup_report_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type){	cgc->cmd[0] = GPCMD_REPORT_KEY;	cgc->cmd[10] = type | (agid << 6);	switch (type) {		case 0: case 8: case 5: {			cgc->buflen = 8;			break;		}		case 1: {			cgc->buflen = 16;			break;		}		case 2: case 4: {			cgc->buflen = 12;			break;		}	}	cgc->cmd[9] = cgc->buflen;	cgc->data_direction = CGC_DATA_READ;}static void setup_send_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type){	cgc->cmd[0] = GPCMD_SEND_KEY;	cgc->cmd[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->cmd[9] = cgc->buflen;	cgc->data_direction = CGC_DATA_WRITE;}static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai){	int ret;	u_char buf[20];	struct cdrom_generic_command cgc;	struct cdrom_device_ops *cdo = cdi->ops;	rpc_state_t rpc_state;	memset(buf, 0, sizeof(buf));	init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);	switch (ai->type) {	/* LU data send */	case DVD_LU_SEND_AGID:		cdinfo(CD_DVD, "entering DVD_LU_SEND_AGID\n"); 		setup_report_key(&cgc, ai->lsa.agid, 0);		if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		ai->lsa.agid = buf[7] >> 6;		/* Returning data, let host change state */		break;	case DVD_LU_SEND_KEY1:		cdinfo(CD_DVD, "entering DVD_LU_SEND_KEY1\n"); 		setup_report_key(&cgc, ai->lsk.agid, 2);		if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		copy_key(ai->lsk.key, &buf[4]);		/* Returning data, let host change state */		break;	case DVD_LU_SEND_CHALLENGE:		cdinfo(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n"); 		setup_report_key(&cgc, ai->lsc.agid, 1);		if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		copy_chal(ai->lsc.chal, &buf[4]);		/* Returning data, let host change state */		break;	/* Post-auth key */	case DVD_LU_SEND_TITLE_KEY:		cdinfo(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n"); 		setup_report_key(&cgc, ai->lstk.agid, 4);		cgc.cmd[5] = ai->lstk.lba;		cgc.cmd[4] = ai->lstk.lba >> 8;		cgc.cmd[3] = ai->lstk.lba >> 16;		cgc.cmd[2] = ai->lstk.lba >> 24;		if ((ret = cdo->generic_packet(cdi, &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]);		/* Returning data, let host change state */		break;	case DVD_LU_SEND_ASF:		cdinfo(CD_DVD, "entering DVD_LU_SEND_ASF\n"); 		setup_report_key(&cgc, ai->lsasf.agid, 5);				if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		ai->lsasf.asf = buf[7] & 1;		break;	/* LU data receive (LU changes state) */	case DVD_HOST_SEND_CHALLENGE:		cdinfo(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n"); 		setup_send_key(&cgc, ai->hsc.agid, 1);		buf[1] = 0xe;		copy_chal(&buf[4], ai->hsc.chal);		if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		ai->type = DVD_LU_SEND_KEY1;		break;	case DVD_HOST_SEND_KEY2:		cdinfo(CD_DVD, "entering DVD_HOST_SEND_KEY2\n"); 		setup_send_key(&cgc, ai->hsk.agid, 3);		buf[1] = 0xa;		copy_key(&buf[4], ai->hsk.key);		if ((ret = cdo->generic_packet(cdi, &cgc))) {			ai->type = DVD_AUTH_FAILURE;			return ret;		}		ai->type = DVD_AUTH_ESTABLISHED;		break;	/* Misc */	case DVD_INVALIDATE_AGID:		cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 		setup_report_key(&cgc, ai->lsa.agid, 0x3f);		if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		break;	/* Get region settings */	case DVD_LU_SEND_RPC_STATE:		cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");		setup_report_key(&cgc, 0, 8);		memset(&rpc_state, 0, sizeof(rpc_state_t));		cgc.buffer = (char *) &rpc_state;		if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		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;	/* Set region settings */	case DVD_HOST_SEND_RPC_STATE:		cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");		setup_send_key(&cgc, 0, 6);		buf[1] = 6;		buf[4] = ai->hrpcs.pdrc;		if ((ret = cdo->generic_packet(cdi, &cgc)))			return ret;		break;	default:		cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);		return -ENOTTY;	}	return 0;}static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s){	int ret, i;	u_char buf[4 + 4 * 20], *base;	struct dvd_layer *layer;	struct cdrom_generic_command cgc;	struct cdrom_device_ops *cdo = cdi->ops;	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;	cgc.cmd[6] = s->physical.layer_num;	cgc.cmd[7] = s->type;	cgc.cmd[9] = cgc.buflen & 0xff;	if ((ret = cdo->generic_packet(cdi, &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(struct cdrom_device_info *cdi, dvd_struct *s){	int ret;	u_char buf[8];	struct cdrom_generic_command cgc;	struct cdrom_device_ops *cdo = cdi->ops;	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;	cgc.cmd[6] = s->copyright.layer_num;	cgc.cmd[7] = s->type;	cgc.cmd[8] = cgc.buflen >> 8;	cgc.cmd[9] = cgc.buflen & 0xff;	if ((ret = cdo->generic_packet(cdi, &cgc)))		return ret;	s->copyright.cpst = buf[4];	s->copyright.rmi = buf[5];	return 0;}static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s){	int ret, size;	u_char *buf;	struct cdrom_generic_command cgc;	struct cdrom_device_ops *cdo = cdi->ops;	size = sizeof(s->disckey.value) + 4;	if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)		return -ENOMEM;	init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;	cgc.cmd[7] = s->type;	cgc.cmd[8] = size >> 8;	cgc.cmd[9] = size & 0xff;	cgc.cmd[10] = s->disckey.agid << 6;	if (!(ret = cdo->generic_packet(cdi, &cgc)))		memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));	kfree(buf);	return ret;}static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s){	int ret;	u_char buf[4 + 188];	struct cdrom_generic_command cgc;	struct cdrom_device_ops *cdo = cdi->ops;	init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;	cgc.cmd[7] = s->type;	cgc.cmd[9] = cgc.buflen = 0xff;	if ((ret = cdo->generic_packet(cdi, &cgc)))		return ret;	s->bca.len = buf[0] << 8 | buf[1];	if (s->bca.len < 12 || s->bca.len > 188) {		cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);		return -EIO;	}	memcpy(s->bca.value, &buf[4], s->bca.len);	return 0;}static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s){	int ret = 0, size;	u_char *buf;	struct cdrom_generic_command cgc;	struct cdrom_device_ops *cdo = cdi->ops;	size = sizeof(s->manufact.value) + 4;

⌨️ 快捷键说明

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