root/trunk/freebob/src/avdescriptor.cpp

Revision 24, 7.6 kB (checked in by pieterpalmers, 19 years ago)

- bugfix: descriptor was not read correctly in AvDescriptor?
- several other small bugfixes/cleanups
- fix compiler warnings
- added some extra debug statements to follow parser flow

  • 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 }
45
46 AvDescriptor::~AvDescriptor()
47 {
48         if (bOpen) {
49                 Close();
50         }
51         if (aContents) {
52                 delete aContents;
53         }
54
55 }
56
57 void AvDescriptor::OpenReadOnly() {
58         quadlet_t *response;
59         quadlet_t request[3];   
60        
61         if (!cParent) {
62                 return;
63         }
64        
65         if(isOpen()) {
66                 Close();
67         }
68        
69         request[0] = AVC1394_CTYPE_CONTROL | qTarget
70                                         | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
71         request[1] = 0x01FFFFFF;
72         //fprintf(stderr, "Opening descriptor\n");
73        
74         response =  cParent->avcExecuteTransaction(request, 2, 2);
75        
76         if ((response[0]&0xFF000000)==AVC1394_RESPONSE_ACCEPTED) {
77                 bOpen=true;
78                 iAccessType=0x01;
79         } else {
80                 Close();
81                 bOpen=false;
82         }
83 }
84
85 void AvDescriptor::OpenReadWrite() {
86         quadlet_t *response;
87         quadlet_t request[3];   
88        
89         if (!cParent) {
90                 return;
91         }
92        
93         if(isOpen()) {
94                 Close();
95         }
96                
97         request[0] = AVC1394_CTYPE_CONTROL | qTarget
98                                         | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
99         request[1] = 0x03FFFFFF;
100         //fprintf(stderr, "Opening descriptor\n");
101        
102         response =  cParent->avcExecuteTransaction(request, 2, 2);
103        
104         if ((response[0]&0xFF000000)==AVC1394_RESPONSE_ACCEPTED) {
105                 bOpen=true;
106                 iAccessType=0x03;
107         } else {
108                 Close();
109                 bOpen=false;
110         }
111 }
112
113 bool AvDescriptor::canWrite() {
114         if(bOpen && (iAccessType==0x03) && cParent) {
115                 return true;
116         } else {
117                 return false;
118         }
119 }
120
121 void AvDescriptor::Close() {
122         quadlet_t *response;
123         quadlet_t request[3];   
124         if (!cParent) {
125                 return;
126         }       
127         request[0] = AVC1394_CTYPE_CONTROL | qTarget
128                                         | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
129         request[1] = 0x00FFFFFF;
130         //fprintf(stderr, "Opening descriptor\n");
131        
132         response =  cParent->avcExecuteTransaction(request, 2, 2);
133        
134         if ((response[0]&0xFF000000)==AVC1394_RESPONSE_ACCEPTED) { // should always be accepted according to spec
135                 bOpen=false;
136         }
137 }
138
139 /* Load the descriptor
140  * no error checking yet
141  */
142
143 void AvDescriptor::Load() {
144         quadlet_t *response;
145         quadlet_t request[3];   
146         unsigned int i=0;
147         unsigned int bytes_read=0;
148         unsigned char *databuffer;
149         unsigned char read_result_status;
150         unsigned int data_length_read;
151        
152         if (!cParent) {
153                 return;
154         }
155        
156         /* First determine the descriptor length */
157         request[0] = AVC1394_CTYPE_CONTROL | qTarget
158                                         | AVC1394_COMMAND_READ_DESCRIPTOR | (iType & 0xFF);
159         request[1] = 0xFFFF0000 | (0x02);
160         request[2] = (((0)&0xFFFF) << 16) |0x0000FFFF;
161         response =  cParent->avcExecuteTransaction(request, 3, 3);
162
163         iLength=response[2] & 0xFFFF;
164        
165         fprintf(stderr,"Descriptor length=0x%04X %d\n",iLength,iLength);       
166
167         // now get the rest of the descriptor
168         aContents=new unsigned char[iLength];
169        
170         /* there is a gap in the read data, because of the two bytes
171          * that are before the third quadlet (why did 1394TA do that?)
172          *
173          * proposed solution:
174          * 1) the first read is OK, because the length of the descriptor is in these two bytes,
175          *    so execute a read from address 0 with length=iLength
176          * 2) process the bytes starting from response[3]
177          * 3) the next reads should start from the end of the previous read minus 2. this way we
178          *    can discard these two problem bytes, because they are already read in the previous
179          *    run.
180          */
181        
182         // first read
183         if(bytes_read<iLength) {
184                 fprintf(stderr,".");   
185                 // apparently the lib modifies the request, so redefine it completely
186                 request[0] = AVC1394_CTYPE_CONTROL | qTarget
187                                                 | AVC1394_COMMAND_READ_DESCRIPTOR | (iType & 0xFF);
188                 // the amount of bytes we want to read is:
189                 //  total descriptor length + 2 bytes of the descriptor length field (i.e. the overlap bytes for this read)
190                 request[1] = 0xFFFF0000 | (iLength)&0xFFFF;
191                 request[2] = ((0) << 16) |0x0000FFFF;
192                
193                 response =  cParent->avcExecuteTransaction(request, 3, 3);
194                 data_length_read=(response[1]&0xFFFF);
195                 read_result_status=((response[1]>>24)&0xFF);
196                
197                 databuffer=(unsigned char *)(response+3);
198                
199                 // the buffer starting at databuffer is two bytes smaller that the amount of bytes read
200                 for (i=0;(i<data_length_read-2) && (bytes_read < iLength);i++) {
201                         *(aContents+bytes_read)=*(databuffer+i);
202                         bytes_read++;
203                 }
204                
205         }
206        
207         // now do the remaining reads
208         while(bytes_read<iLength) {
209                 fprintf(stderr,".");   
210                 // apparently the lib modifies the request, so redefine it completely
211                 request[0] = AVC1394_CTYPE_CONTROL | qTarget
212                                                 | AVC1394_COMMAND_READ_DESCRIPTOR | (iType & 0xFF);
213                 // the amount of bytes we want to read is:
214                 //  (total descriptor length - number of bytes already read) + 2 overlap with previous read
215                 request[1] = 0xFFFF0000 | (iLength-bytes_read+2)&0xFFFF;
216                 request[2] = (((bytes_read)&0xFFFF) << 16) |0x0000FFFF;
217                
218                 response =  cParent->avcExecuteTransaction(request, 3, 3);
219                 data_length_read=(response[1]&0xFFFF);
220                 read_result_status=((response[1]>>24)&0xFF);
221                
222                 databuffer=(unsigned char *)(response+3);
223                
224                 for (i=0;(i<data_length_read-2) && (bytes_read < iLength);i++) {
225                         *(aContents+bytes_read)=*(databuffer+i);
226                         bytes_read++;
227                 }
228                
229         }
230         fprintf(stderr,"\n");   
231        
232        
233         bLoaded=true;
234 }
235
236 bool AvDescriptor::isPresent() {
237         quadlet_t *response;
238         quadlet_t request[2];   
239        
240         if (!cParent) {
241                 return false;
242         }
243        
244         request[0] = AVC1394_CTYPE_STATUS | qTarget | AVC1394_COMMAND_OPEN_DESCRIPTOR | (iType & 0xFF);
245         request[1] = 0xFFFFFFFF;
246         response =  cParent->avcExecuteTransaction(request, 2, 2);
247
248         if (((response[0] & 0xFF000000)==AVC1394_RESPONSE_NOT_IMPLEMENTED) || ((response[1] & 0xFF000000)==0x04)) {
249                 fprintf(stderr,"Descriptor not present.\n");
250                 return false;
251         }
252         return true;
253 }
254
255
256 bool AvDescriptor::isOpen() {
257         // maybe we should check this on the device instead of mirroring locally...
258         // after all it can time out
259         return bOpen;
260 }
261
262 bool AvDescriptor::isLoaded() {
263         return bLoaded;
264 }
265
266 unsigned int AvDescriptor::getLength() {
267         return iLength;
268 }
269
270 unsigned char AvDescriptor::readByte(unsigned int address) {
271         if(cParent && bLoaded && aContents) {
272                 return *(aContents+address);
273         } else {
274                 return 0; // what to do with this?
275         }
276 }
277
278 unsigned int AvDescriptor::readWord(unsigned int address) {
279         unsigned int word;
280        
281         if(cParent && bLoaded && aContents) {
282                 word=(*(aContents+address)<<8)+*(aContents+address+1);
283                 return word;
284         } else {
285                 return 0; // what to do with this?
286         }
287 }
288
289 unsigned int AvDescriptor::readBuffer(unsigned int address, unsigned int length, unsigned char *buffer) {
290         if(cParent && bLoaded && aContents && address < iLength) {
291                 if(address+length>iLength) {
292                         length=iLength-address;
293                 }
294                 memcpy((void*)buffer, (void*)(aContents+address), length);
295                 return length;
296                
297         } else {
298                 return 0;
299         }
300 }
Note: See TracBrowser for help on using the browser.