root/trunk/freebob/src/avdescriptor.cpp

Revision 25, 7.7 kB (checked in by pieterpalmers, 19 years ago)

- updated the AvMusicStatusDescriptor? to automatically parse itself upon creation

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* avdescriptor.cpp
2  * Copyright (C) 2004 by Pieter Palmers
3  *
4  * This file is part of FreeBob.
5  *
6  * FreeBob is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBob 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 FreeBob; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "avdescriptor.h"
22 #include <string.h>
23 #include <errno.h>
24 #include <libavc1394/avc1394.h>
25 #include <libavc1394/avc1394_vcr.h>
26 #include "debugmodule.h"
27
28 /* should probably be attached to an AVC device,
29    a descriptor is attached to an AVC device anyway.
30    
31    a descriptor also always has a type
32 */
33
34 AvDescriptor::AvDescriptor(AvDevice *parent, quadlet_t target, unsigned int type)
35 {
36         cParent=parent;
37         iType=type;
38         qTarget=target;
39         aContents=NULL;
40         bLoaded=false;
41         iLength=0;
42         bOpen=false;
43         iAccessType=0;
44         bValid=false; // don't know yet what I'm going to do with this in the generic descriptor
45 }
46
47 AvDescriptor::~AvDescriptor()
48 {
49         if (bOpen) {
50                 Close();
51         }
52         if (aContents) {
53                 delete aContents;
54         }
55
56 }
57
58 void AvDescriptor::OpenReadOnly() {
59         quadlet_t *response;
60         quadlet_t request[3];   
61        
62         if (!cParent) {
63                 return;
64         }
65        
66         if(isOpen()) {
67                 Close();
68         }
69        
70         request[0] = AVC1394_CTYPE_CONTROL | qTarget
71                                         | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
72         request[1] = 0x01FFFFFF;
73         //fprintf(stderr, "Opening descriptor\n");
74        
75         response =  cParent->avcExecuteTransaction(request, 2, 2);
76        
77         if ((response[0]&0xFF000000)==AVC1394_RESPONSE_ACCEPTED) {
78                 bOpen=true;
79                 iAccessType=0x01;
80         } else {
81                 Close();
82                 bOpen=false;
83         }
84 }
85
86 void AvDescriptor::OpenReadWrite() {
87         quadlet_t *response;
88         quadlet_t request[3];   
89        
90         if (!cParent) {
91                 return;
92         }
93        
94         if(isOpen()) {
95                 Close();
96         }
97                
98         request[0] = AVC1394_CTYPE_CONTROL | qTarget
99                                         | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
100         request[1] = 0x03FFFFFF;
101         //fprintf(stderr, "Opening descriptor\n");
102        
103         response =  cParent->avcExecuteTransaction(request, 2, 2);
104        
105         if ((response[0]&0xFF000000)==AVC1394_RESPONSE_ACCEPTED) {
106                 bOpen=true;
107                 iAccessType=0x03;
108         } else {
109                 Close();
110                 bOpen=false;
111         }
112 }
113
114 bool AvDescriptor::canWrite() {
115         if(bOpen && (iAccessType==0x03) && cParent) {
116                 return true;
117         } else {
118                 return false;
119         }
120 }
121
122 void AvDescriptor::Close() {
123         quadlet_t *response;
124         quadlet_t request[3];   
125         if (!cParent) {
126                 return;
127         }       
128         request[0] = AVC1394_CTYPE_CONTROL | qTarget
129                                         | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
130         request[1] = 0x00FFFFFF;
131         //fprintf(stderr, "Opening descriptor\n");
132        
133         response =  cParent->avcExecuteTransaction(request, 2, 2);
134        
135         if ((response[0]&0xFF000000)==AVC1394_RESPONSE_ACCEPTED) { // should always be accepted according to spec
136                 bOpen=false;
137         }
138 }
139
140 /* Load the descriptor
141  * no error checking yet
142  */
143
144 void AvDescriptor::Load() {
145         quadlet_t *response;
146         quadlet_t request[3];   
147         unsigned int i=0;
148         unsigned int bytes_read=0;
149         unsigned char *databuffer;
150         unsigned char read_result_status;
151         unsigned int data_length_read;
152        
153         if (!cParent) {
154                 return;
155         }
156        
157         /* First determine the descriptor length */
158         request[0] = AVC1394_CTYPE_CONTROL | qTarget
159                                         | AVC1394_COMMAND_READ_DESCRIPTOR | (iType & 0xFF);
160         request[1] = 0xFFFF0000 | (0x02);
161         request[2] = (((0)&0xFFFF) << 16) |0x0000FFFF;
162         response =  cParent->avcExecuteTransaction(request, 3, 3);
163
164         iLength=response[2] & 0xFFFF;
165        
166         fprintf(stderr,"Descriptor length=0x%04X %d\n",iLength,iLength);       
167
168         // now get the rest of the descriptor
169         aContents=new unsigned char[iLength];
170        
171         /* there is a gap in the read data, because of the two bytes
172          * that are before the third quadlet (why did 1394TA do that?)
173          *
174          * proposed solution:
175          * 1) the first read is OK, because the length of the descriptor is in these two bytes,
176          *    so execute a read from address 0 with length=iLength
177          * 2) process the bytes starting from response[3]
178          * 3) the next reads should start from the end of the previous read minus 2. this way we
179          *    can discard these two problem bytes, because they are already read in the previous
180          *    run.
181          */
182        
183         // first read
184         if(bytes_read<iLength) {
185                 fprintf(stderr,".");   
186                 // apparently the lib modifies the request, so redefine it completely
187                 request[0] = AVC1394_CTYPE_CONTROL | qTarget
188                                                 | AVC1394_COMMAND_READ_DESCRIPTOR | (iType & 0xFF);
189                 // the amount of bytes we want to read is:
190                 //  total descriptor length + 2 bytes of the descriptor length field (i.e. the overlap bytes for this read)
191                 request[1] = 0xFFFF0000 | (iLength)&0xFFFF;
192                 request[2] = ((0) << 16) |0x0000FFFF;
193                
194                 response =  cParent->avcExecuteTransaction(request, 3, 3);
195                 data_length_read=(response[1]&0xFFFF);
196                 read_result_status=((response[1]>>24)&0xFF);
197                
198                 databuffer=(unsigned char *)(response+3);
199                
200                 // the buffer starting at databuffer is two bytes smaller that the amount of bytes read
201                 for (i=0;(i<data_length_read-2) && (bytes_read < iLength);i++) {
202                         *(aContents+bytes_read)=*(databuffer+i);
203                         bytes_read++;
204                 }
205                
206         }
207        
208         // now do the remaining reads
209         while(bytes_read<iLength) {
210                 fprintf(stderr,".");   
211                 // apparently the lib modifies the request, so redefine it completely
212                 request[0] = AVC1394_CTYPE_CONTROL | qTarget
213                                                 | AVC1394_COMMAND_READ_DESCRIPTOR | (iType & 0xFF);
214                 // the amount of bytes we want to read is:
215                 //  (total descriptor length - number of bytes already read) + 2 overlap with previous read
216                 request[1] = 0xFFFF0000 | (iLength-bytes_read+2)&0xFFFF;
217                 request[2] = (((bytes_read)&0xFFFF) << 16) |0x0000FFFF;
218                
219                 response =  cParent->avcExecuteTransaction(request, 3, 3);
220                 data_length_read=(response[1]&0xFFFF);
221                 read_result_status=((response[1]>>24)&0xFF);
222                
223                 databuffer=(unsigned char *)(response+3);
224                
225                 for (i=0;(i<data_length_read-2) && (bytes_read < iLength);i++) {
226                         *(aContents+bytes_read)=*(databuffer+i);
227                         bytes_read++;
228                 }
229                
230         }
231         fprintf(stderr,"\n");   
232        
233        
234         bLoaded=true;
235 }
236
237 bool AvDescriptor::isPresent() {
238         quadlet_t *response;
239         quadlet_t request[2];   
240        
241         if (!cParent) {
242                 return false;
243         }
244        
245         request[0] = AVC1394_CTYPE_STATUS | qTarget | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
246         request[1] = 0xFFFFFFFF;
247         response =  cParent->avcExecuteTransaction(request, 2, 2);
248
249         if (((response[0] & 0xFF000000)==AVC1394_RESPONSE_NOT_IMPLEMENTED) || ((response[1] & 0xFF000000)==0x04)) {
250                 fprintf(stderr,"Descriptor not present.\n");
251                 bValid=false;
252                 return false;
253         }
254         return true;
255 }
256
257
258 bool AvDescriptor::isOpen() {
259         // maybe we should check this on the device instead of mirroring locally...
260         // after all it can time out
261         return bOpen;
262 }
263
264 bool AvDescriptor::isLoaded() {
265         return bLoaded;
266 }
267
268 bool AvDescriptor::isValid() {
269         return bValid;
270 }
271
272
273 unsigned int AvDescriptor::getLength() {
274         return iLength;
275 }
276
277 unsigned char AvDescriptor::readByte(unsigned int address) {
278         if(cParent && bLoaded && aContents) {
279                 return *(aContents+address);
280         } else {
281                 return 0; // what to do with this?
282         }
283 }
284
285 unsigned int AvDescriptor::readWord(unsigned int address) {
286         unsigned int word;
287        
288         if(cParent && bLoaded && aContents) {
289                 word=(*(aContents+address)<<8)+*(aContents+address+1);
290                 return word;
291         } else {
292                 return 0; // what to do with this?
293         }
294 }
295
296 unsigned int AvDescriptor::readBuffer(unsigned int address, unsigned int length, unsigned char *buffer) {
297         if(cParent && bLoaded && aContents && address < iLength) {
298                 if(address+length>iLength) {
299                         length=iLength-address;
300                 }
301                 memcpy((void*)buffer, (void*)(aContents+address), length);
302                 return length;
303                
304         } else {
305                 return 0;
306         }
307 }
Note: See TracBrowser for help on using the browser.