32 * @param aPort Owning CAcmPort object. |
33 * @param aPort Owning CAcmPort object. |
33 * @param aBufSize Required buffer size. |
34 * @param aBufSize Required buffer size. |
34 * @return Ownership of a newly created CAcmWriter object |
35 * @return Ownership of a newly created CAcmWriter object |
35 */ |
36 */ |
36 { |
37 { |
37 OstTraceFunctionEntry0( CACMWRITER_NEWL_ENTRY ); |
38 LOG_STATIC_FUNC_ENTRY |
|
39 |
38 CAcmWriter* self = new(ELeave) CAcmWriter(aPort, aBufSize); |
40 CAcmWriter* self = new(ELeave) CAcmWriter(aPort, aBufSize); |
39 CleanupStack::PushL(self); |
41 CleanupStack::PushL(self); |
40 self->ConstructL(); |
42 self->ConstructL(); |
41 CLEANUPSTACK_POP(self); |
43 CLEANUPSTACK_POP(self); |
42 OstTraceFunctionExit0( CACMWRITER_NEWL_EXIT ); |
|
43 return self; |
44 return self; |
44 } |
45 } |
45 |
46 |
46 CAcmWriter::~CAcmWriter() |
47 CAcmWriter::~CAcmWriter() |
47 /** |
48 /** |
48 * Destructor. |
49 * Destructor. |
49 */ |
50 */ |
50 { |
51 { |
51 OstTraceFunctionEntry0( CACMWRITER_CACMWRITER_DES_ENTRY ); |
52 LOG_FUNC |
|
53 |
52 WriteCancel(); |
54 WriteCancel(); |
|
55 |
53 delete iBuffer; |
56 delete iBuffer; |
54 OstTraceFunctionExit0( CACMWRITER_CACMWRITER_DES_EXIT ); |
|
55 } |
57 } |
56 |
58 |
57 void CAcmWriter::Write(const TAny* aClientBuffer, TUint aLength) |
59 void CAcmWriter::Write(const TAny* aClientBuffer, TUint aLength) |
58 /** |
60 /** |
59 * Queue a write. |
61 * Queue a write. |
60 * |
62 * |
61 * @param aClientBuffer pointer to the Client's buffer |
63 * @param aClientBuffer pointer to the Client's buffer |
62 * @param aLength Number of bytes to write |
64 * @param aLength Number of bytes to write |
63 */ |
65 */ |
64 { |
66 { |
65 OstTraceFunctionEntry0( CACMWRITER_WRITE_ENTRY ); |
67 LOGTEXT3(_L8("CAcmWriter::Write aClientBuffer=0x%08x, aLength=%d"), |
66 OstTraceExt2( TRACE_NORMAL, CACMWRITER_WRITE, "CAcmWriter::Write;aClientBuffer=%p;aLength=%d", aClientBuffer, (TInt)aLength ); |
68 aClientBuffer, aLength); |
67 |
69 |
68 // Check we're open to requests and make a note of interesting data. |
70 // Check we're open to requests and make a note of interesting data. |
69 CheckNewRequest(aClientBuffer, aLength); |
71 CheckNewRequest(aClientBuffer, aLength); |
70 |
72 |
71 // If the write size greater than the current buffer size then the |
73 // If the write size greater than the current buffer size then the |
74 |
76 |
75 // Get as much data as we can from the client into our buffer |
77 // Get as much data as we can from the client into our buffer |
76 ReadDataFromClient(); |
78 ReadDataFromClient(); |
77 // ...and write as much as we've got to the LDD |
79 // ...and write as much as we've got to the LDD |
78 IssueWrite(); |
80 IssueWrite(); |
79 OstTraceFunctionExit0( CACMWRITER_WRITE_EXIT ); |
|
80 } |
81 } |
81 |
82 |
82 void CAcmWriter::WriteCancel() |
83 void CAcmWriter::WriteCancel() |
83 /** |
84 /** |
84 * Cancel a write. |
85 * Cancel a write. |
85 */ |
86 */ |
86 { |
87 { |
87 OstTraceFunctionEntry0( CACMWRITER_WRITECANCEL_ENTRY ); |
88 LOG_FUNC |
|
89 |
88 // Cancel any outstanding request on the LDD. |
90 // Cancel any outstanding request on the LDD. |
89 if ( iPort.Acm() ) |
91 if ( iPort.Acm() ) |
90 { |
92 { |
91 OstTrace0( TRACE_NORMAL, CACMWRITER_WRITECANCEL, "CAcmWriter::WriteCancel;\tiPort.Acm() exists- calling WriteCancel on it" ); |
93 LOGTEXT(_L8("\tiPort.Acm() exists- calling WriteCancel on it")); |
92 iPort.Acm()->WriteCancel(); |
94 iPort.Acm()->WriteCancel(); |
93 } |
95 } |
94 |
96 |
95 // Reset our flag to say there's no current outstanding request. What's |
97 // Reset our flag to say there's no current outstanding request. What's |
96 // already in our buffer can stay there. |
98 // already in our buffer can stay there. |
97 iCurrentRequest.iClientPtr = NULL; |
99 iCurrentRequest.iClientPtr = NULL; |
98 OstTraceFunctionExit0( CACMWRITER_WRITECANCEL_EXIT ); |
|
99 } |
100 } |
100 |
101 |
101 void CAcmWriter::ResetBuffer() |
102 void CAcmWriter::ResetBuffer() |
102 /** |
103 /** |
103 * Called by the port to clear the buffer. |
104 * Called by the port to clear the buffer. |
104 */ |
105 */ |
105 { |
106 { |
106 OstTraceFunctionEntry0( CACMWRITER_RESETBUFFER_ENTRY ); |
107 LOG_FUNC |
|
108 |
107 // A request is outstanding- C32 should protect against this. |
109 // A request is outstanding- C32 should protect against this. |
108 |
110 __ASSERT_DEBUG(!iCurrentRequest.iClientPtr, |
109 if (iCurrentRequest.iClientPtr != NULL) |
111 _USB_PANIC(KAcmPanicCat, EPanicInternalError)); |
110 { |
112 |
111 OstTrace1( TRACE_FATAL, CACMWRITER_RESETBUFFER, |
|
112 "CAcmWriter::ResetBuffer;EPanicInternalError=%d", |
|
113 (TInt)EPanicInternalError ); |
|
114 __ASSERT_DEBUG( EFalse, User::Panic(KAcmPanicCat, EPanicInternalError) ); |
|
115 } |
|
116 // Don't have anything to do. There are no pointers to reset. This |
113 // Don't have anything to do. There are no pointers to reset. This |
117 // function may in the future (if we support KConfigWriteBufferedComplete) |
114 // function may in the future (if we support KConfigWriteBufferedComplete) |
118 // do work, so leave the above assertion in. |
115 // do work, so leave the above assertion in. |
119 OstTraceFunctionExit0( CACMWRITER_RESETBUFFER_EXIT ); |
|
120 } |
116 } |
121 |
117 |
122 TInt CAcmWriter::SetBufSize(TUint aSize) |
118 TInt CAcmWriter::SetBufSize(TUint aSize) |
123 /** |
119 /** |
124 * Called by the port to set the buffer size. Also used as a utility by us to |
120 * Called by the port to set the buffer size. Also used as a utility by us to |
125 * create the buffer at instantiation. |
121 * create the buffer at instantiation. |
126 * |
122 * |
127 * @param aSize The required size of the buffer. |
123 * @param aSize The required size of the buffer. |
128 */ |
124 */ |
129 { |
125 { |
130 OstTraceFunctionEntry0( CACMWRITER_SETBUFSIZE_ENTRY ); |
126 LOG_FUNC |
131 OstTrace1( TRACE_NORMAL, CACMWRITER_SETBUFSIZE, "CAcmWriter::SetBufSize;aSize=%d", (TInt)aSize ); |
127 LOGTEXT2(_L8("\taSize=%d"), aSize); |
132 |
128 |
133 if ( iCurrentRequest.iClientPtr ) |
129 if ( iCurrentRequest.iClientPtr ) |
134 { |
130 { |
135 // A request is outstanding. C32 does not protect us against this. |
131 // A request is outstanding. C32 does not protect us against this. |
136 OstTrace0( TRACE_NORMAL, CACMWRITER_SETBUFSIZE_DUP1, |
132 LOGTEXT(_L8("\t***a request is outstanding- returning KErrInUse")); |
137 "CAcmWriter::SetBufSize;\t***a request is outstanding- returning KErrInUse" ); |
|
138 OstTraceFunctionExit0( CACMWRITER_SETBUFSIZE_EXIT ); |
|
139 return KErrInUse; |
133 return KErrInUse; |
140 } |
134 } |
141 |
135 |
142 // Create the new buffer. |
136 // Create the new buffer. |
143 HBufC8* newBuf = HBufC8::New(static_cast<TInt>(aSize)); |
137 HBufC8* newBuf = HBufC8::New(static_cast<TInt>(aSize)); |
144 if ( !newBuf ) |
138 if ( !newBuf ) |
145 { |
139 { |
146 OstTrace0( TRACE_NORMAL, CACMWRITER_SETBUFSIZE_DUP2, |
140 LOGTEXT(_L8("\tfailed to create new buffer- returning KErrNoMemory")); |
147 "CAcmWriter::SetBufSize;\tfailed to create new buffer- returning KErrNoMemory" ); |
|
148 OstTraceFunctionExit0( CACMWRITER_SETBUFSIZE_EXIT_DUP1 ); |
|
149 return KErrNoMemory; |
141 return KErrNoMemory; |
150 } |
142 } |
151 delete iBuffer; |
143 delete iBuffer; |
152 iBuffer = newBuf; |
144 iBuffer = newBuf; |
153 iBuf.Set(iBuffer->Des()); |
145 iBuf.Set(iBuffer->Des()); |
154 iBufSize = aSize; |
146 iBufSize = aSize; |
155 |
147 |
156 OstTraceFunctionExit0( CACMWRITER_SETBUFSIZE_EXIT_DUP2 ); |
|
157 return KErrNone; |
148 return KErrNone; |
158 } |
149 } |
159 |
150 |
160 CAcmWriter::CAcmWriter(CAcmPort& aPort, |
151 CAcmWriter::CAcmWriter(CAcmPort& aPort, |
161 TUint aBufSize) |
152 TUint aBufSize) |
167 */ |
158 */ |
168 : iBufSize(aBufSize), |
159 : iBufSize(aBufSize), |
169 iBuf(NULL,0,0), |
160 iBuf(NULL,0,0), |
170 iPort(aPort) |
161 iPort(aPort) |
171 { |
162 { |
172 OstTraceFunctionEntry0( CACMWRITER_CACMWRITER_CONS_ENTRY ); |
|
173 OstTraceFunctionExit0( CACMWRITER_CACMWRITER_CONS_EXIT ); |
|
174 } |
163 } |
175 |
164 |
176 void CAcmWriter::ConstructL() |
165 void CAcmWriter::ConstructL() |
177 /** |
166 /** |
178 * 2nd-phase constructor. |
167 * 2nd-phase constructor. |
179 */ |
168 */ |
180 { |
169 { |
181 OstTraceFunctionEntry0( CACMWRITER_CONSTRUCTL_ENTRY ); |
|
182 // Create the required buffer. |
170 // Create the required buffer. |
183 OstTrace0( TRACE_NORMAL, CACMWRITER_CONSTRUCTL, "CAcmWriter::ConstructL;\tabout to create iBuffer" ); |
171 LOGTEXT(_L8("\tabout to create iBuffer")); |
184 TInt err = SetBufSize(iBufSize); |
172 LEAVEIFERRORL(SetBufSize(iBufSize)); |
185 if (err < 0) |
|
186 { |
|
187 OstTrace1( TRACE_ERROR, CACMWRITER_CONSTRUCTL_DUP1, "CAcmWriter::ConstructL;err=%d", err ); |
|
188 User::Leave(err); |
|
189 } |
|
190 OstTraceFunctionExit0( CACMWRITER_CONSTRUCTL_EXIT ); |
|
191 } |
173 } |
192 |
174 |
193 void CAcmWriter::WriteCompleted(TInt aError) |
175 void CAcmWriter::WriteCompleted(TInt aError) |
194 /** |
176 /** |
195 * This function is called when a write on the LDD has completed. |
177 * This function is called when a write on the LDD has completed. |
198 * left or an error occurs. |
180 * left or an error occurs. |
199 * |
181 * |
200 * @param aError Error with which the write completed. |
182 * @param aError Error with which the write completed. |
201 */ |
183 */ |
202 { |
184 { |
203 OstTraceFunctionEntry0( CACMWRITER_WRITECOMPLETED_ENTRY ); |
185 LOG_FUNC |
204 OstTrace1( TRACE_NORMAL, CACMWRITER_WRITECOMPLETED, "CAcmWriter::WriteCompleted;aError=%d", (TInt)aError ); |
186 LOGTEXT2(_L8("\taError=%d"), aError); |
|
187 |
205 if(iLengthToGo == 0 || aError != KErrNone) |
188 if(iLengthToGo == 0 || aError != KErrNone) |
206 { |
189 { |
207 OstTrace1( TRACE_NORMAL, CACMWRITER_WRITECOMPLETED_DUP1, |
190 LOGTEXT2(_L8("\tcompleting request with %d"), aError); |
208 "CAcmWriter::WriteCompleted;\tcompleting request with %d", aError ); |
|
209 CompleteRequest(aError); |
191 CompleteRequest(aError); |
210 } |
192 } |
211 else |
193 else |
212 { |
194 { |
213 //there is some data remaining to be read so reissue the Read & Write |
195 //there is some data remaining to be read so reissue the Read & Write |
214 //requests until there is no data left. |
196 //requests until there is no data left. |
215 ReadDataFromClient(); |
197 ReadDataFromClient(); |
216 IssueWrite(); |
198 IssueWrite(); |
217 } |
199 } |
218 OstTraceFunctionExit0( CACMWRITER_WRITECOMPLETED_EXIT ); |
|
219 } |
200 } |
220 |
201 |
221 void CAcmWriter::ReadDataFromClient() |
202 void CAcmWriter::ReadDataFromClient() |
222 /** |
203 /** |
223 * Read data from the client space into the internal buffer, prior to writing. |
204 * Read data from the client space into the internal buffer, prior to writing. |
224 */ |
205 */ |
225 { |
206 { |
226 OstTraceFunctionEntry0( CACMWRITER_READDATAFROMCLIENT_ENTRY ); |
207 LOG_FUNC |
227 TPtr8 ptr((TUint8*)iBuf.Ptr(), |
208 TPtr8 ptr((TUint8*)iBuf.Ptr(), |
228 0, |
209 0, |
229 Min(iBuf.MaxLength(), iLengthToGo)); |
210 Min(iBuf.MaxLength(), iLengthToGo)); |
230 |
211 |
231 TInt err = iPort.IPCRead(iCurrentRequest.iClientPtr, |
212 TInt err = iPort.IPCRead(iCurrentRequest.iClientPtr, |
232 ptr, |
213 ptr, |
233 static_cast<TInt>(iOffsetIntoClientsMemory)); |
214 static_cast<TInt>(iOffsetIntoClientsMemory)); |
234 OstTrace1( TRACE_NORMAL, CACMWRITER_READDATAFROMCLIENT, "CAcmWriter::ReadDataFromClient;\tIPCRead = %d", err ); |
215 LOGTEXT2(_L8("\tIPCRead = %d"), err); |
|
216 iBuf.SetLength(ptr.Length()); |
|
217 __ASSERT_DEBUG(!err, _USB_PANIC(KAcmPanicCat, EPanicInternalError)); |
235 |
218 |
236 iBuf.SetLength(ptr.Length()); |
|
237 if (err != 0) |
|
238 { |
|
239 OstTrace1( TRACE_FATAL, CACMWRITER_READDATAFROMCLIENT_DUP1, |
|
240 "CAcmWriter::ReadDataFromClient;EPanicInternalError=%d", |
|
241 (TInt)EPanicInternalError ); |
|
242 __ASSERT_DEBUG( EFalse, User::Panic(KAcmPanicCat, EPanicInternalError) ); |
|
243 } |
|
244 static_cast<void>(err); |
219 static_cast<void>(err); |
|
220 |
245 // Increase our pointer (into the client's space) of already-read data. |
221 // Increase our pointer (into the client's space) of already-read data. |
246 iOffsetIntoClientsMemory += iBuf.Length(); |
222 iOffsetIntoClientsMemory += iBuf.Length(); |
247 OstTraceFunctionExit0( CACMWRITER_READDATAFROMCLIENT_EXIT ); |
|
248 } |
223 } |
249 |
224 |
250 |
225 |
251 |
226 |
252 void CAcmWriter::CheckNewRequest(const TAny* aClientBuffer, TUint aLength) |
227 void CAcmWriter::CheckNewRequest(const TAny* aClientBuffer, TUint aLength) |
257 * |
232 * |
258 * @param aClientBuffer Pointer to the client's memory space. |
233 * @param aClientBuffer Pointer to the client's memory space. |
259 * @param aLength Length to write. |
234 * @param aLength Length to write. |
260 */ |
235 */ |
261 { |
236 { |
262 OstTraceFunctionEntry0( CACMWRITER_CHECKNEWREQUEST_ENTRY ); |
237 LOG_FUNC |
263 |
238 |
264 if (aLength > static_cast<TUint>(KMaxTInt)) |
239 __ASSERT_DEBUG(aLength <= static_cast<TUint>(KMaxTInt), |
265 { |
240 _USB_PANIC(KAcmPanicCat, EPanicInternalError)); |
266 OstTrace1( TRACE_FATAL, CACMWRITER_CHECKNEWREQUEST, |
241 |
267 "CAcmWriter::CheckNewRequest;aLength > static_cast<TUint>(KMaxTInt), EPanicInternalError=%d", |
|
268 (TInt)EPanicInternalError ); |
|
269 __ASSERT_DEBUG( EFalse, User::Panic(KAcmPanicCat, EPanicInternalError) ); |
|
270 } |
|
271 // Check we have no outstanding request already. |
242 // Check we have no outstanding request already. |
272 if ( iCurrentRequest.iClientPtr ) |
243 if ( iCurrentRequest.iClientPtr ) |
273 { |
244 { |
274 OstTrace1( TRACE_FATAL, CACMWRITER_CHECKNEWREQUEST_DUP1, |
245 _USB_PANIC(KAcmPanicCat, EPanicInternalError); |
275 "CAcmWriter::CheckNewRequest;iCurrentRequest.iClientPtr != NULL, EPanicInternalError=%d", |
|
276 (TInt)EPanicInternalError ); |
|
277 __ASSERT_DEBUG( EFalse, User::Panic(KAcmPanicCat, EPanicInternalError) ); |
|
278 } |
246 } |
279 // Sanity check on what C32 gave us. |
247 // Sanity check on what C32 gave us. |
280 if (aClientBuffer == NULL) |
248 __ASSERT_DEBUG(aClientBuffer, |
281 { |
249 _USB_PANIC(KAcmPanicCat, EPanicInternalError)); |
282 OstTrace1( TRACE_FATAL, CACMWRITER_CHECKNEWREQUEST_DUP2, |
250 |
283 "CAcmWriter::CheckNewRequest;aClientBuffer == NULL, EPanicInternalError=%d", |
|
284 (TInt)EPanicInternalError ); |
|
285 __ASSERT_DEBUG( EFalse, User::Panic(KAcmPanicCat, EPanicInternalError) ); |
|
286 } |
|
287 // Make a note of interesting data. |
251 // Make a note of interesting data. |
288 iCurrentRequest.iLength = aLength; |
252 iCurrentRequest.iLength = aLength; |
289 iCurrentRequest.iClientPtr = aClientBuffer; |
253 iCurrentRequest.iClientPtr = aClientBuffer; |
290 |
254 |
291 iLengthToGo = aLength; |
255 iLengthToGo = aLength; |
292 iOffsetIntoClientsMemory = 0; |
256 iOffsetIntoClientsMemory = 0; |
293 OstTraceFunctionExit0( CACMWRITER_CHECKNEWREQUEST_EXIT ); |
|
294 } |
257 } |
295 |
258 |
296 void CAcmWriter::CompleteRequest(TInt aError) |
259 void CAcmWriter::CompleteRequest(TInt aError) |
297 /** |
260 /** |
298 * Utility to reset our 'outstanding request' flag and complete the client's |
261 * Utility to reset our 'outstanding request' flag and complete the client's |
299 * request back to them. |
262 * request back to them. |
300 * |
263 * |
301 * @param aError The error code to complete with. |
264 * @param aError The error code to complete with. |
302 */ |
265 */ |
303 { |
266 { |
304 OstTraceFunctionEntry0( CACMWRITER_COMPLETEREQUEST_ENTRY ); |
267 LOGTEXT2(_L8("CAcmWriter::CompleteRequest aError=%d"), aError); |
305 OstTrace1( TRACE_NORMAL, CACMWRITER_COMPLETEREQUEST, |
268 |
306 "CAcmWriter::CompleteRequest;CAcmWriter::CompleteRequest aError=%d", (TInt)aError ); |
|
307 |
|
308 // Set our flag to say that we no longer have an outstanding request. |
269 // Set our flag to say that we no longer have an outstanding request. |
309 iCurrentRequest.iClientPtr = NULL; |
270 iCurrentRequest.iClientPtr = NULL; |
310 OstTrace1( TRACE_NORMAL, CACMWRITER_COMPLETEREQUEST_DUP1, |
271 |
311 "CAcmWriter::CompleteRequest;\tcalling WriteCompleted with %d", aError ); |
272 LOGTEXT2(_L8("\tcalling WriteCompleted with %d"), aError); |
312 |
|
313 iPort.WriteCompleted(aError); |
273 iPort.WriteCompleted(aError); |
314 OstTraceFunctionExit0( CACMWRITER_COMPLETEREQUEST_EXIT ); |
|
315 } |
274 } |
316 |
275 |
317 void CAcmWriter::IssueWrite() |
276 void CAcmWriter::IssueWrite() |
318 /** |
277 /** |
319 * Writes a batch of data from our buffer to the LDD. Currently writes the |
278 * Writes a batch of data from our buffer to the LDD. Currently writes the |
320 * entire load of buffered data in one go. |
279 * entire load of buffered data in one go. |
321 */ |
280 */ |
322 { |
281 { |
323 OstTraceFunctionEntry0( CACMWRITER_ISSUEWRITE_ENTRY ); |
282 LOG_FUNC |
324 |
283 |
325 OstTrace1( TRACE_NORMAL, CACMWRITER_ISSUEWRITE, "CAcmWriter::IssueWrite;\tissuing Write of %d bytes", (TInt)(iBuf.Length()) ); |
284 LOGTEXT2(_L8("\tissuing Write of %d bytes"), iBuf.Length()); |
326 if (iPort.Acm() == NULL) |
285 __ASSERT_DEBUG(iPort.Acm(), |
327 { |
286 _USB_PANIC(KAcmPanicCat, EPanicInternalError)); |
328 OstTrace1( TRACE_FATAL, CACMWRITER_ISSUEWRITE_DUP1, |
|
329 "CAcmWriter::IssueWrite;EPanicInternalError=%d", (TInt)EPanicInternalError); |
|
330 __ASSERT_DEBUG( EFalse, User::Panic(KAcmPanicCat, EPanicInternalError) ); |
|
331 } |
|
332 iPort.Acm()->Write(*this, |
287 iPort.Acm()->Write(*this, |
333 iBuf, |
288 iBuf, |
334 iBuf.Length()); |
289 iBuf.Length()); |
335 |
290 |
336 #ifdef DEBUG |
291 #ifdef DEBUG |
339 // that the LengthToGo is also 0, if it is not then we may end up looping through this |
294 // that the LengthToGo is also 0, if it is not then we may end up looping through this |
340 // code until a driver write error occurs which may never happen. |
295 // code until a driver write error occurs which may never happen. |
341 // This is not expected to occur but the test is in here just to be safe. |
296 // This is not expected to occur but the test is in here just to be safe. |
342 if(iBuf.Length() == 0 && iCurrentRequest.Length() != 0 && iLengthToGo != 0) |
297 if(iBuf.Length() == 0 && iCurrentRequest.Length() != 0 && iLengthToGo != 0) |
343 { |
298 { |
344 OstTrace1( TRACE_FATAL, CACMWRITER_ISSUEWRITE_DUP2, |
299 _USB_PANIC(KAcmPanicCat, EPanicInternalError); |
345 "CAcmWriter::IssueWrite;EPanicInternalError=%d", (TInt)EPanicInternalError); |
|
346 __ASSERT_DEBUG( EFalse, User::Panic(KAcmPanicCat, EPanicInternalError) ); |
|
347 } |
300 } |
348 #endif |
301 #endif |
349 // Update our counter of remaining data to write. |
302 // Update our counter of remaining data to write. |
350 iLengthToGo -= iBuf.Length(); |
303 iLengthToGo -= iBuf.Length(); |
351 OstTraceFunctionExit0( CACMWRITER_ISSUEWRITE_EXIT ); |
|
352 } |
304 } |
353 |
305 |
354 // |
306 // |
355 // End of file |
307 // End of file |