SonyCDU948.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:5k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1999  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: SonyCDU948.cc,v $
  21.  * Revision 1.3  1999/05/24 17:32:59  mueller
  22.  * Added CD-TEXT writing.
  23.  *
  24.  * Revision 1.2  1999/05/20 19:47:15  mueller
  25.  * Updated implementation.
  26.  *
  27.  * Revision 1.1  1999/05/15 20:11:56  mueller
  28.  * Initial revision
  29.  *
  30.  */
  31. static char rcsid[] = "$Id: SonyCDU948.cc,v 1.3 1999/05/24 17:32:59 mueller Exp mueller $";
  32. #include <config.h>
  33. #include <string.h>
  34. #include <assert.h>
  35. #include "SonyCDU948.h"
  36. #include "PWSubChannel96.h"
  37. #include "util.h"
  38. #include "Toc.h"
  39. #include "CdTextEncoder.h"
  40. SonyCDU948::SonyCDU948(ScsiIf *scsiIf, unsigned long options)
  41.   : SonyCDU920(scsiIf, options)
  42. {
  43.   driverName_ = "Sony CDU948 - Version 0.1 (data) (alpha)";
  44.   speed_ = 4;
  45.   cdTextEncoder_ = NULL;
  46. }
  47. SonyCDU948::~SonyCDU948()
  48. {
  49.   delete cdTextEncoder_;
  50.   cdTextEncoder_ = NULL;
  51. }
  52. // static constructor
  53. CdrDriver *SonyCDU948::instance(ScsiIf *scsiIf, unsigned long options)
  54. {
  55.   return new SonyCDU948(scsiIf, options);
  56. }
  57. int SonyCDU948::checkToc(const Toc *toc)
  58. {
  59.   int err = SonyCDU920::checkToc(toc);
  60.   int e;
  61.   if ((e = toc->checkCdTextData()) > err)
  62.     err = e;
  63.   return err;
  64. }
  65. int SonyCDU948::multiSession(int m)
  66. {
  67.   multiSession_ = m != 0 ? 1 : 0;
  68.   return 0;
  69. }
  70. // sets speed
  71. // return: 0: OK
  72. //         1: illegal speed
  73. int SonyCDU948::speed(int s)
  74. {
  75.   if (s == 0 || s == 1 || s == 2 || s == 4)
  76.     speed_ = s;
  77.   else if (s == 3)
  78.     speed_ = 2;
  79.   else if (s > 4)
  80.     speed_ = 4;
  81.   else
  82.     return 1;
  83.   return 0;
  84. }
  85. // sets read/write speed and simulation mode
  86. // return: 0: OK
  87. //         1: scsi command failed
  88. int SonyCDU948::selectSpeed()
  89. {
  90.   unsigned char mp[4];
  91.   
  92.   mp[0] = 0x31;
  93.   mp[1] = 2;
  94.   mp[2] = 0;
  95.   mp[3] = 0;
  96.   switch (speed_) {
  97.   case 0:
  98.     mp[2] = 0xff;
  99.   case 1:
  100.     mp[2] = 0;
  101.     break;
  102.   case 2:
  103.     mp[2] = 1;
  104.     break;
  105.   case 4:
  106.     mp[2] = 3;
  107.     break;
  108.   }
  109.   if (setModePage6(mp, NULL, NULL, 1) != 0) {
  110.     message(-2, "Cannot set speed mode page.");
  111.     return 1;
  112.   }
  113.   return 0;
  114. }
  115. // Sets write parameters.
  116. // return: 0: OK
  117. //         1: scsi command failed
  118. int SonyCDU948::setWriteParameters()
  119. {
  120.   unsigned char cmd[10];
  121.   unsigned char data[52];
  122.   if (SonyCDU920::setWriteParameters() != 0)
  123.     return 1;
  124.   memset(cmd, 0, 10);
  125.   memset(data, 0, 52);
  126.   cmd[0] = 0xf8; // SET WRITE PARAMETERS
  127.   cmd[7] = 0;
  128.   cmd[8] = 52;
  129.   data[1] = 50;
  130.   data[3] = (multiSession_ != 0 ? (3 << 6) : 0);
  131.   
  132.   if (sendCmd(cmd, 10, data, 52, NULL, 0, 1) != 0) {
  133.     message(-1, "Cannot set write parameters.");
  134.     return 1;
  135.   }
  136.   return 0;
  137. }
  138. int SonyCDU948::initDao(const Toc *toc)
  139. {
  140.   long n;
  141.   delete cdTextEncoder_;
  142.   cdTextEncoder_ = new CdTextEncoder(toc);
  143.   if (cdTextEncoder_->encode() != 0) {
  144.     message(-2, "CD-TEXT encoding failed.");
  145.     return 1;
  146.   }
  147.   if (cdTextEncoder_->getSubChannels(&n) == NULL || n == 0) {
  148.     // there is no CD-TEXT data to write
  149.     delete cdTextEncoder_;
  150.     cdTextEncoder_ = NULL;
  151.   }
  152.   return SonyCDU920::initDao(toc);
  153. }
  154. int SonyCDU948::startDao()
  155. {
  156.   unsigned char leadInDataForm = 0x00; // CD-DA, generate data by device
  157.   scsiTimeout_ = scsiIf_->timeout(3 * 60);
  158.   if (cdTextEncoder_ != NULL)
  159.     leadInDataForm = 0xc0; // CD-DA with P-W sub-channel data
  160.   if (setWriteParameters() != 0 ||
  161.       sendCueSheet(leadInDataForm) != 0)
  162.     return 1;
  163.   if (writeCdTextLeadIn() != 0) {
  164.     return 1;
  165.   }
  166.   long lba = -150;
  167.   // write mandatory pre-gap after lead-in
  168.   if (writeZeros(toc_->leadInMode(), lba, 0, 150) != 0) {
  169.     return 1;
  170.   }
  171.   
  172.   return 0;
  173. }
  174. int SonyCDU948::writeCdTextLeadIn()
  175. {
  176.   unsigned char cmd[10];
  177.   const PWSubChannel96 **cdTextSubChannels;
  178.   long cdTextSubChannelCount;
  179.   long channelsPerCmd = scsiIf_->maxDataLen() / 96;
  180.   long scp = 0;
  181.   long byteLen;
  182.   long len = leadInLen_;
  183.   long n;
  184.   long i;
  185.   unsigned char *p;
  186.   if (cdTextEncoder_ == NULL)
  187.     return 0;
  188.   if (leadInLen_ == 0) {
  189.     message(-2, "Cannot write CD-TEXT lead-in because lead-in length is not known.");
  190.     return 1;
  191.   }
  192.   cdTextSubChannels = cdTextEncoder_->getSubChannels(&cdTextSubChannelCount);
  193.   assert(channelsPerCmd > 0);
  194.   assert(cdTextSubChannels != NULL);
  195.   assert(cdTextSubChannelCount > 0);
  196.   message(1, "Writing CD-TEXT lead-in...");
  197.   memset(cmd, 0, 10);
  198.   cmd[0] = 0xe1; // WRITE CONTINUE
  199.   while (len > 0) {
  200.     n = (len > channelsPerCmd) ? channelsPerCmd : len;
  201.     byteLen = n * 96;
  202.     cmd[1] = (byteLen >> 16) & 0x1f;
  203.     cmd[2] = byteLen >> 8;
  204.     cmd[3] = byteLen;
  205.     p = transferBuffer_;
  206.     
  207.     for (i = 0; i < n; i++) {
  208.       memcpy(p, cdTextSubChannels[scp]->data(), 96);
  209.       p += 96;
  210.       scp++;
  211.       if (scp >= cdTextSubChannelCount)
  212. scp = 0;
  213.     }
  214.     if (sendCmd(cmd, 10, transferBuffer_, byteLen, NULL, 0) != 0) {
  215.       message(-2, "Writing of CD-TEXT data failed.");
  216.       return 1;
  217.     }
  218.     len -= n;
  219.   }
  220.     
  221.   return 0;
  222. }