Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1702 - 1
/* Copyright (C) 2010-2011 Circuits At Home, LTD. All rights reserved.
2
 
3
This software may be distributed and modified under the terms of the GNU
4
General Public License version 2 (GPL2) as published by the Free Software
5
Foundation and appearing in the file GPL2.TXT included in the packaging of
6
this file. Please note that GPL2 Section 2[b] requires that all works based
7
on this software must also be made publicly available under the terms of
8
the GPL2 ("Copyleft").
9
 
10
Contact information
11
-------------------
12
 
13
Circuits At Home, LTD
14
Web      :  http://www.circuitsathome.com
15
e-mail   :  support@circuitsathome.com
16
*/
17
#include "ptpconst.h"
18
#include "ptp.h"
19
#include "ptpdebug.h"
20
 
21
void PTP::SetInitialState()
22
{
23
        busyTime = 0;
24
        hangTime = 0;
25
        idSession = 0;
26
        idTransaction = 0;
27
        SetState(PTP_STATE_SESSION_NOT_OPENED);
28
}
29
 
30
void PTPStateHandlers::OnDeviceDisconnectedState(PTP *ptp)
31
{
32
}
33
 
34
void PTPStateHandlers::OnSessionNotOpenedState(PTP *ptp)
35
{
36
        if (ptp->OpenSession() == PTP_RC_OK)
37
        {
38
                PTPTRACE("Session opened\r\n");
39
                ptp->SetState(PTP_STATE_SESSION_OPENED);
40
        }
41
}
42
 
43
void PTPStateHandlers::OnSessionOpenedState(PTP *ptp)
44
{
45
        ptp->SetState(PTP_STATE_DEVICE_INITIALIZED);
46
}
47
 
48
void PTPStateHandlers::OnDeviceInitializedState(PTP *ptp)
49
{
50
}
51
 
52
void PTPStateHandlers::OnDeviceNotRespondingState(PTP *ptp)
53
{
54
}
55
 
56
void PTPStateHandlers::OnDeviceBusyState(PTP *ptp)
57
{
58
}
59
 
60
void uint16_to_char(uint16_t integer, unsigned char *data)
61
{
62
        data[0] = (integer & 0xff);
63
        data[1] = ((integer >> 8) & 0xff);
64
}
65
 
66
void uint32_to_char(uint32_t integer, unsigned char *data)
67
{
68
        data[0] = (integer & 0xff);
69
        data[1] = ((integer >> 8) & 0xff);
70
        data[2] = ((integer >> 16) & 0xff);
71
        data[3] = ((integer >> 24) & 0xff);
72
}
73
 
74
void char_to_uint16(unsigned char *scan)
75
{
76
        char= scan[0];
77
        scan[0] = scan[1];
78
        scan[1] = c;
79
}
80
 
81
void char_to_uint32(unsigned char *scan)
82
{
83
        char= scan[0];
84
        scan[0] = scan[3];
85
        scan[3] = c;
86
        c               = scan[1];
87
        scan[1] = scan[2];
88
        scan[2] = c;
89
}
90
 
91
void UsbStringToASCII(uint8_t *str)
92
{
93
    uint8_t i, j, len = (uint8_t)str[0];    
94
 
95
    // length and descriptor type one byte each should be skipped
96
    for (i=0, j=2; j<len; i++, j+=2)
97
        str[i] = str[j];
98
    str[i] = 0;
99
}
100
 
101
void Notify(const char* msg)
102
{
103
        if(!msg) return;
104
        char c;
105
 
106
        while((c = pgm_read_byte(msg++)))
107
                Serial.print(c,BYTE);
108
}
109
 
110
void Message(const char* msg, uint16_t rcode = 0)
111
{
112
        Notify(msg);
113
        Notify(PSTR(": "));
114
        PrintHex<uint16_t>(rcode);
115
        Notify(PSTR("\r\n"));
116
}
117
 
118
//void Message(const char* msg, uint16_t rcode = 0)
119
//{
120
//      Notify(msg);
121
//      msg = PSTR(": 0x");
122
//      Notify(msg);
123
//
124
//    uint16_t    mask = 0x1000;
125
//    
126
//    while (mask > 1)
127
//    {
128
//              if (rcode < mask)
129
//                      Serial.print("0");
130
//              mask >>= 4;
131
//    }
132
//      Serial.println( rcode, HEX );
133
//}
134
 
135
PTP::PTP(uint8_t addr, uint8_t epin, uint8_t epout, uint8_t epint, uint8_t nconf, PTPStateHandlers *s) :
136
        theState(0),
137
        busyTime(0),
138
        hangTime(0),
139
        idTransaction(0),
140
        idSession(0),
141
        devAddress(addr),
142
        epDataIn(epin),
143
        epDataOut(epout),
144
        epInterrupt(epint),
145
        numConf(nconf),
146
        stateMachine(s)
147
{
148
};
149
 
150
void PTP::Task2()
151
{
152
        switch (theState)
153
        {
154
        //case PTP_STATE_DEVICE_DISCONNECTED:
155
//              idSession = 0;
156
//              idTransaction = 0;
157
//              if (stateMachine)
158
        //              stateMachine->OnDeviceDisconnectedState(this);
159
        //      break;
160
        case PTP_STATE_SESSION_NOT_OPENED:
161
                if (stateMachine)
162
                        stateMachine->OnSessionNotOpenedState(this);
163
                break;
164
        case PTP_STATE_SESSION_OPENED:
165
                if (stateMachine)
166
                        stateMachine->OnSessionOpenedState(this);
167
                break;
168
        case PTP_STATE_DEVICE_INITIALIZED:
169
                if (stateMachine)
170
                        stateMachine->OnDeviceInitializedState(this);
171
                break;
172
        case PTP_STATE_DEVICE_NOT_RESPONDING:
173
                if (stateMachine)
174
                        stateMachine->OnDeviceNotRespondingState(this);
175
                break;
176
        case PTP_STATE_DEVICE_BUSY:
177
                if (stateMachine)
178
                        stateMachine->OnDeviceBusyState(this);
179
                break;
180
        // Error state
181
        default:
182
                ;
183
        }
184
}
185
 
186
uint16_t PTP::Transaction(uint16_t opcode, OperFlags *flags, uint32_t *params = NULL, void *pVoid = NULL)
187
{
188
        uint8_t         rcode;
189
        {
190
                uint8_t         cmd[PTP_USB_BULK_HDR_LEN + 12];         // header + 3 uint32_t parameters
191
 
192
                ZerroMemory(PTP_USB_BULK_HDR_LEN + 12, cmd);
193
 
194
                // Make command PTP container header
195
                uint16_to_char(PTP_USB_CONTAINER_COMMAND,       (unsigned char*)(cmd + PTP_CONTAINER_CONTYPE_OFF));                     // type
196
                uint16_to_char(opcode,                                          (unsigned char*)(cmd + PTP_CONTAINER_OPCODE_OFF));                      // code
197
                uint32_to_char(idTransaction++,                         (unsigned char*)(cmd + PTP_CONTAINER_TRANSID_OFF));                     // transaction id
198
 
199
                uint8_t         n = flags->opParams, len;
200
 
201
                if (params && *params)
202
                {
203
                        *((uint8_t*)cmd) = len = PTP_USB_BULK_HDR_LEN + (n << 2);
204
 
205
                        for (uint32_t *p1 = (uint32_t*)(cmd + PTP_CONTAINER_PAYLOAD_OFF), *p2 = (uint32_t*)params; n--; p1++, p2++)
206
                                uint32_to_char(*p2, (unsigned char*)p1);
207
                }
208
                else
209
                        *((uint8_t*)cmd) = len = PTP_USB_BULK_HDR_LEN;
210
 
211
                rcode = Usb.outTransfer(devAddress, epDataOut, len, (char*)cmd);
212
 
213
                if (rcode)
214
                {
215
                        PTPTRACE2("Transaction: Command block send error", rcode);
216
                        return PTP_RC_GeneralError;
217
                }
218
        }
219
        {
220
                uint8_t         data[PTP_MAX_RX_BUFFER_LEN];
221
 
222
                if (flags->txOperation)
223
                {
224
                        if (flags->typeOfVoid && !pVoid)
225
                        {
226
                                PTPTRACE("Transaction: pVoid is NULL\n");
227
                                return PTP_RC_GeneralError;
228
                        }
229
                        ZerroMemory(PTP_MAX_RX_BUFFER_LEN, data);
230
 
231
                        uint32_t        bytes_left =    (flags->typeOfVoid == 3) ? PTP_USB_BULK_HDR_LEN + flags->dataSize :
232
                                                        ((flags->typeOfVoid == 1) ? PTP_USB_BULK_HDR_LEN + ((PTPDataSupplier*)pVoid)->GetDataSize() : 12);
233
 
234
                        // Make data PTP container header
235
                        *((uint32_t*)data) = bytes_left;
236
                        uint16_to_char(PTP_USB_CONTAINER_DATA,  (unsigned char*)(data + PTP_CONTAINER_CONTYPE_OFF));            // type
237
                        uint16_to_char(opcode,                                  (unsigned char*)(data + PTP_CONTAINER_OPCODE_OFF));                     // code
238
                        uint32_to_char(idTransaction,                   (unsigned char*)(data + PTP_CONTAINER_TRANSID_OFF));            // transaction id
239
 
240
                        uint16_t        len;
241
 
242
                        if (flags->typeOfVoid == 1)
243
                                len = (bytes_left < PTP_MAX_RX_BUFFER_LEN) ? bytes_left : PTP_MAX_RX_BUFFER_LEN;
244
 
245
                        if (flags->typeOfVoid == 3)
246
                        {
247
                                uint8_t         *p1 = (data + PTP_USB_BULK_HDR_LEN);
248
                                uint8_t         *p2 = (uint8_t*)pVoid;
249
 
250
                                for (uint8_t i=flags->dataSize; i; i--, p1++, p2++)
251
                                        *p1 = *p2;
252
 
253
                                len = PTP_USB_BULK_HDR_LEN + flags->dataSize;
254
                        }
255
                        bool first_time = true;
256
 
257
                        while (bytes_left)
258
                        {
259
                                if (flags->typeOfVoid == 1)
260
                                        ((PTPDataSupplier*)pVoid)->GetData(     (first_time) ? len - PTP_USB_BULK_HDR_LEN : len,
261
                                                                                                                (first_time) ? (data + PTP_USB_BULK_HDR_LEN) : data);
262
 
263
                                rcode = Usb.outTransfer(devAddress, epDataOut, len, (char*)data);
264
 
265
                                if (rcode)
266
                                {
267
                                        PTPTRACE2("Transaction: Data block send error.", rcode);
268
                                        return PTP_RC_GeneralError;
269
                                }
270
 
271
                                bytes_left -= len;
272
 
273
                                len = (bytes_left < PTP_MAX_RX_BUFFER_LEN) ? bytes_left : PTP_MAX_RX_BUFFER_LEN;
274
 
275
                                first_time = false;
276
                        }
277
                }
278
 
279
                // Because inTransfer does not return the actual number of bytes recieved, it should be 
280
                // calculated here.
281
                uint32_t        total = 0, data_off = 0;        // Total PTP data packet size, Data offset
282
                uint8_t         inbuffer = 0;                   // Number of bytes read into buffer
283
                uint16_t        loops = 0;                      // Number of loops necessary to get all the data from device
284
                uint8_t         timeoutcnt = 0;
285
 
286
                while (1)
287
                {
288
                        ZerroMemory(PTP_MAX_RX_BUFFER_LEN, data);
289
 
290
                        rcode = Usb.inTransfer(devAddress, epDataIn, PTP_MAX_RX_BUFFER_LEN, (char*)data);
291
 
292
                        if (rcode)
293
                        {
294
                                PTPTRACE("Fatal USB Error\r\n");
295
 
296
                                // in some cases NAK handling might be necessary
297
                                PTPTRACE2("Transaction: Response recieve error", rcode);
298
                                return PTP_RC_GeneralError;
299
                        }
300
 
301
                        // This can occure in case of unsupported operation or successive response after data reception stage
302
                        if ((!loops || total == data_off) && *((uint16_t*)(data + PTP_CONTAINER_CONTYPE_OFF)) == PTP_USB_CONTAINER_RESPONSE)
303
                        {
304
                                uint16_t        response = *((uint16_t*)(data + PTP_CONTAINER_OPCODE_OFF));
305
 
306
                                if (response == PTP_RC_OK && *((uint32_t*)data) > PTP_USB_BULK_HDR_LEN)
307
                                {
308
                                        // number of params = (container length - 12) / 4
309
                                        uint8_t n = (*((uint32_t*)data) - PTP_USB_BULK_HDR_LEN) >> 2;
310
 
311
                                        // BUG: n should be checked!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
312
                                        flags->rsParams = n;
313
 
314
                                        for (uint32_t *p1 = (uint32_t*)(data + PTP_USB_BULK_HDR_LEN), *p2 = (uint32_t*)params; n; n--, p1++, p2++)
315
                                                p2 = p1;
316
                                }
317
                                if (response != PTP_RC_OK)
318
                                {
319
                                        PTPTRACE2("Transaction: Response recieve error", response);
320
                                        data_off = 0;
321
                                }
322
                                return response;
323
                        }
324
 
325
                        if (loops == 0)
326
                        {
327
                                total           =       *((uint32_t*)data);
328
                                inbuffer        =       (total < PTP_MAX_RX_BUFFER_LEN) ? (uint8_t)total : PTP_MAX_RX_BUFFER_LEN;
329
                        }
330
                        else
331
                                inbuffer = ((total - data_off) > PTP_MAX_RX_BUFFER_LEN) ? PTP_MAX_RX_BUFFER_LEN : (uint8_t)(total - data_off);
332
 
333
                        if (pVoid)
334
                        {
335
                                if (flags->typeOfVoid == 0x01)
336
                                        ((PTPReadParser*)pVoid)->Parse(inbuffer, data, (const uint32_t&)data_off);
337
 
338
                                if (flags->typeOfVoid == 0x03)
339
                                        for (uint32_t i=0, j=data_off; i<inbuffer && j<flags->dataSize; i++, j++)
340
                                                ((uint8_t*)pVoid)[j] = data[i];
341
                        }
342
                        data_off += inbuffer;
343
 
344
                        loops ++;
345
                        //delay(10);
346
                } // while(1)
347
        } // end of scope
348
}
349
 
350
 
351
uint16_t PTP::EventCheck(PTPReadParser *pParser)
352
{
353
        uint8_t         data[PTP_MAX_EV_BUFFER_LEN];
354
        uint8_t         rcode;
355
 
356
        // Because inTransfer does not return the actual number of bytes recieved, it should be 
357
        // calculated here.
358
        uint32_t        total = 0, data_off = 0;
359
        uint8_t         inbuffer = 0;
360
        uint16_t        loops = 0;
361
        uint8_t         timeoutcnt = 0;
362
 
363
        while (1)
364
        {
365
                ZerroMemory(PTP_MAX_EV_BUFFER_LEN, data);
366
 
367
                rcode = Usb.inTransfer(devAddress, epInterrupt, PTP_MAX_EV_BUFFER_LEN, (char*)data);
368
 
369
                switch (rcode)
370
                {
371
                // In case of no event occured
372
                case 0xFF:
373
                                return PTP_EC_Undefined;
374
 
375
                default:
376
                        // in case of a usb error
377
                        PTPTRACE2("EventCheck USB error: ", rcode);
378
                        return PTP_RC_GeneralError;
379
                }
380
 
381
                if (loops == 0)
382
                {
383
                        total           =       *((uint32_t*)data);
384
                        inbuffer        =       (total < PTP_MAX_EV_BUFFER_LEN) ? (uint8_t)total : PTP_MAX_EV_BUFFER_LEN;
385
                }
386
                else
387
                        inbuffer = ((total - data_off) > PTP_MAX_EV_BUFFER_LEN) ? PTP_MAX_EV_BUFFER_LEN : (uint8_t)(total - data_off);
388
 
389
                if (pParser)
390
                        pParser->Parse(inbuffer, data, (const uint32_t&)data_off);
391
 
392
                data_off += inbuffer;
393
 
394
                loops ++;
395
                delay(50);
396
        } // while(1)
397
}
398
 
399
bool PTP::CheckEvent(uint8_t size, uint8_t *buf)
400
{
401
        ZerroMemory(size, buf);
402
 
403
        uint8_t rcode = Usb.inTransfer(devAddress, epInterrupt, size, (char*)buf);
404
 
405
        // if no interrupts pending - return false
406
 
407
        // there should be some error type checking involved i.e. timeout error
408
        if (rcode)
409
                return false;
410
 
411
        return true;
412
}
413
 
414
bool PTP::EventWait(uint8_t size, uint8_t *event_buf, uint16_t timeout)
415
{
416
        const uint16_t  milisec = 0xA0;         // must be polling interval for the interrupt pipe
417
        bool                    occured = false;
418
 
419
        while (!(occured = CheckEvent(size, event_buf)) && (timeout -= milisec))
420
                delay(milisec);
421
 
422
        return occured;
423
}
424
 
425
uint16_t PTP::OpenSession()
426
{
427
        uint32_t        params[1];
428
        OperFlags       flags = { 1, 0, 0, 0, 0, 0 };
429
 
430
        idSession               = 1;
431
        idTransaction   = 1;
432
 
433
        params[0]       = idSession;
434
 
435
        return Transaction(PTP_OC_OpenSession, &flags, params);
436
}
437
 
438
uint16_t PTP::ResetDevice()
439
{
440
        OperFlags       flags = { 0, 0, 0, 0, 0, 0 };
441
        return Transaction(PTP_OC_ResetDevice, &flags);
442
}
443
 
444
uint16_t PTP::GetNumObjects(uint32_t &retval, uint32_t storage_id, uint16_t format, uint32_t assoc)
445
{
446
        uint16_t        ptp_error = PTP_RC_GeneralError;
447
        OperFlags       flags = { 3, 1, 0, 0, 0, 0 };
448
        uint32_t        params[3];
449
 
450
        if ( (ptp_error = Transaction(PTP_OC_GetNumObjects, &flags, params)) == PTP_RC_OK)
451
                retval = params[0];
452
 
453
        return ptp_error;
454
}
455
 
456
uint16_t PTP::GetObject(uint32_t handle, PTPReadParser *parser)
457
{
458
        OperFlags       flags = { 1, 0, 0, 1, 1, 0 };
459
        uint32_t        params[1];
460
 
461
        params[0] = handle;
462
 
463
        return Transaction(PTP_OC_GetObject, &flags, params, parser);
464
}
465
 
466
uint16_t PTP::GetThumb(uint32_t handle, PTPReadParser *parser)
467
{
468
        OperFlags       flags = { 1, 0, 0, 1, 1, 0 };
469
        uint32_t        params[1];
470
 
471
        params[0] = handle;
472
 
473
        return Transaction(PTP_OC_GetThumb, &flags, params, parser);
474
}
475
 
476
uint16_t PTP::DeleteObject(uint32_t handle, uint16_t format)
477
{
478
        OperFlags       flags = { 2, 0, 0, 0, 0, 0 };
479
        uint32_t        params[2];
480
 
481
        params[0] = handle;
482
        params[1] = (uint32_t)format;
483
 
484
        return Transaction(PTP_OC_DeleteObject, &flags, params);
485
}
486
 
487
uint16_t PTP::SetObjectProtection(uint32_t handle, uint16_t attrib)
488
{
489
        OperFlags       flags = { 2, 0, 0, 0, 0, 0 };
490
        uint32_t        params[2];
491
 
492
        params[0] = handle;
493
        params[1] = (uint32_t)attrib;
494
 
495
        return Transaction(PTP_OC_SetObjectProtection, &flags, params);
496
}
497
 
498
uint16_t PTP::MoveObject(uint32_t handle, uint32_t storage_id, uint32_t parent)
499
{
500
        OperFlags       flags = { 3, 0, 0, 0, 0, 0 };
501
        uint32_t        params[2];
502
 
503
        params[0] = handle;
504
        params[1] = storage_id;
505
        params[2] = parent;
506
 
507
        return Transaction(PTP_OC_MoveObject, &flags, params);
508
}
509
 
510
uint16_t PTP::CopyObject(uint32_t handle, uint32_t storage_id, uint32_t parent, uint32_t &new_handle)
511
{
512
        uint16_t        ptp_error = PTP_RC_GeneralError;
513
        OperFlags       flags = { 3, 1, 0, 0, 0, 0 };
514
        uint32_t        params[3];
515
 
516
        params[0] = handle;
517
        params[1] = storage_id;
518
        params[2] = parent;
519
 
520
        if ( (ptp_error = Transaction(PTP_OC_CopyObject, &flags, params)) == PTP_RC_OK)
521
                new_handle = params[0];
522
 
523
        return ptp_error;
524
}
525
 
526
uint16_t PTP::InitiateCapture(uint32_t storage_id, uint16_t format)
527
{
528
        uint16_t        ptp_error = PTP_RC_GeneralError;
529
        OperFlags       flags = { 2, 0, 0, 0, 0, 0 };
530
        uint32_t        params[2];
531
 
532
        params[0] = storage_id;
533
        params[1] = (uint32_t)format;
534
 
535
        if ( (ptp_error = Transaction(PTP_OC_InitiateCapture, &flags, params)) == PTP_RC_OK)
536
        {}
537
 
538
        return ptp_error;
539
}
540
 
541
uint16_t PTP::InitiateOpenCapture(uint32_t storage_id, uint16_t format)
542
{
543
        uint16_t        ptp_error = PTP_RC_GeneralError;
544
        OperFlags       flags = { 2, 0, 0, 0, 0, 0 };
545
        uint32_t        params[2];
546
 
547
        params[0] = storage_id;
548
        params[1] = (uint32_t)format;
549
 
550
        if ( (ptp_error = Transaction(PTP_OC_InitiateOpenCapture, &flags, params)) == PTP_RC_OK)
551
        {}
552
 
553
        return ptp_error;
554
}
555
 
556
uint16_t PTP::TerminateOpenCapture(uint32_t trans_id)
557
{
558
        OperFlags       flags = { 1, 0, 0, 0, 0, 0 };
559
        uint32_t        params[1];
560
 
561
        params[0] = trans_id;
562
 
563
        return Transaction(PTP_OC_TerminateOpenCapture, &flags, params);
564
}
565
 
566
uint16_t PTP::PowerDown()
567
{
568
        OperFlags       flags = { 0, 0, 0, 0, 0, 0 };
569
        return Transaction(PTP_OC_PowerDown, &flags);
570
}
571
 
572
uint16_t PTP::SelfTest(uint16_t type = 0)
573
{
574
        OperFlags       flags = { 1, 0, 0, 0 };
575
        uint32_t        params[1];
576
        params[0]       = type;
577
 
578
        return Transaction(PTP_OC_SelfTest, &flags, params);
579
}
580
 
581
uint16_t PTP::CloseSession()
582
{
583
        uint16_t        ptp_error = PTP_RC_GeneralError;
584
        OperFlags       flags = { 0, 0, 0, 0, 0, 0 };
585
 
586
        if ( (ptp_error = Transaction(PTP_OC_CloseSession, &flags)) == PTP_RC_OK)
587
                idSession = idTransaction = 0;
588
 
589
        return ptp_error;
590
}
591
 
592
uint16_t PTP::GetDeviceInfo(PTPReadParser *parser)
593
{
594
        OperFlags       flags = { 0, 0, 0, 1, 1, 0 };
595
        return Transaction(PTP_OC_GetDeviceInfo, &flags, NULL, parser);
596
}
597
 
598
uint16_t PTP::GetObjectInfo(uint32_t handle, PTPReadParser *parser)
599
{
600
        OperFlags       flags = { 1, 0, 0, 1, 1, 0 };
601
        uint32_t        params[1];
602
        params[0] = handle;
603
 
604
        return Transaction(PTP_OC_GetObjectInfo, &flags, params, parser);
605
}
606
 
607
uint16_t PTP::GetDevicePropDesc(const uint16_t pcode, PTPReadParser *parser)
608
{
609
        OperFlags       flags           = { 1, 0, 0, 1, 1, 0 };
610
        uint32_t        params[1];
611
 
612
        params[0] = (uint32_t)pcode;
613
 
614
        return Transaction(PTP_OC_GetDevicePropDesc, &flags, params, parser);
615
}
616
 
617
uint16_t PTP::GetDevicePropValue(const uint16_t pcode, PTPReadParser *parser)
618
{
619
        OperFlags       flags           = { 1, 0, 0, 1, 1, 0 };
620
        uint32_t        params[1];
621
 
622
        params[0] = (uint32_t)pcode;
623
 
624
        return Transaction(PTP_OC_GetDevicePropValue, &flags, params, parser);
625
}
626
 
627
uint16_t PTP::GetDevicePropValue(const uint16_t pcode, uint8_t &val)
628
{
629
        uint16_t        ptp_error       = PTP_RC_GeneralError;
630
        OperFlags       flags           = { 1, 0, 0, 0, 3, 13 };
631
        uint32_t        params[1];
632
        uint8_t         buf[13];
633
 
634
        params[0] = (uint32_t)pcode;
635
 
636
        if ( (ptp_error = Transaction(PTP_OC_GetDevicePropValue, &flags, params, buf)) == PTP_RC_OK)
637
                val = buf[12];
638
 
639
        return ptp_error;
640
}
641
 
642
uint16_t PTP::GetDevicePropValue(const uint16_t pcode, uint16_t &val)
643
{
644
        uint16_t        ptp_error       = PTP_RC_GeneralError;
645
        OperFlags       flags           = { 1, 0, 0, 0, 3, 14 };
646
        uint32_t        params[1];
647
        uint16_t        buf[7];
648
 
649
        params[0] = pcode;
650
 
651
        if ( (ptp_error = Transaction(PTP_OC_GetDevicePropValue, &flags, params, buf)) == PTP_RC_OK)
652
                val = buf[6];
653
 
654
        return ptp_error;
655
}
656
 
657
uint16_t PTP::GetDevicePropValue(const uint16_t pcode, uint32_t &val)
658
{
659
        uint16_t        ptp_error       = PTP_RC_GeneralError;
660
        OperFlags       flags           = { 1, 0, 0, 0, 3, 16 };
661
        uint32_t        params[1];
662
        uint32_t        buf[4];
663
 
664
        params[0] = pcode;
665
 
666
        if ( (ptp_error = Transaction(PTP_OC_GetDevicePropValue, &flags, params, buf)) == PTP_RC_OK)
667
                val = buf[3];
668
 
669
        return ptp_error;
670
}
671
 
672
uint16_t PTP::SetDevicePropValue(uint16_t pcode, uint8_t val)
673
{
674
        OperFlags       flags           = { 1, 0, 1, 1, 3, 1 };
675
        uint32_t        params[1];
676
        uint8_t         value;
677
 
678
        params[0]       = (uint32_t)pcode;
679
        value           = val;
680
 
681
        return Transaction(PTP_OC_SetDevicePropValue, &flags, params, (void*)&value);
682
}
683
 
684
uint16_t PTP::SetDevicePropValue(uint16_t pcode, uint16_t val)
685
{
686
        OperFlags       flags           = { 1, 0, 1, 1, 3, 2 };
687
        uint32_t        params[1];
688
        uint16_t        value;
689
 
690
        params[0]       = (uint32_t)pcode;
691
        value           = val;
692
 
693
        return Transaction(PTP_OC_SetDevicePropValue, &flags, params, (void*)&value);
694
}
695
 
696
uint16_t PTP::SetDevicePropValue(uint16_t pcode, uint32_t val)
697
{
698
        OperFlags       flags           = { 1, 0, 1, 1, 3, 4 };
699
        uint32_t        params[1];
700
        uint32_t        value;
701
 
702
        params[0]       = (uint32_t)pcode;
703
        value           = val;
704
 
705
        return Transaction(PTP_OC_SetDevicePropValue, &flags, params, (void*)&value);
706
}
707
 
708
uint16_t PTP::ResetDevicePropValue(const uint16_t pcode)
709
{
710
        OperFlags       flags           = { 1, 0, 0, 0 };
711
        uint32_t        params[1];
712
 
713
        params[0] = (uint32_t)pcode;
714
 
715
        return Transaction(PTP_OC_ResetDevicePropValue, &flags, params);
716
}
717
 
718
uint16_t PTP::Operation(uint16_t opcode, uint8_t nparams, uint32_t *params)
719
{
720
        OperFlags       flags           = { 0, 0, 0, 0, 0, 0 };
721
 
722
        flags.opParams = nparams;
723
 
724
        return Transaction(opcode, &flags, params);
725
}
726
 
727
uint16_t PTP::GetStorageInfo(uint32_t storage_id, PTPReadParser *parser)
728
{
729
        OperFlags       flags           = { 1, 0, 0, 1, 1, 0 };
730
 
731
        uint32_t        params[1];
732
        params[0]       = storage_id;
733
 
734
        return Transaction(PTP_OC_GetStorageInfo, &flags, params, parser);
735
}
736
 
737
uint16_t PTP::FormatStore(uint32_t storage_id, uint32_t fsformat)
738
{
739
        OperFlags       flags           = { 2, 0, 0, 0, 0, 0 };
740
 
741
        uint32_t        params[2];
742
        params[0]       = storage_id;
743
        params[1]       = fsformat;
744
 
745
        return Transaction(PTP_OC_FormatStore, &flags, params);
746
}
747
 
748
uint16_t PTP::CaptureImage()
749
{
750
        uint16_t        ptp_error = PTP_RC_GeneralError;
751
        uint32_t        params[2] = {0, 0x00003801};
752
        OperFlags       flags = { 2, 0, 0, 0 };
753
 
754
        if ( (ptp_error = Transaction(PTP_OC_InitiateCapture, &flags, params)) != PTP_RC_OK)
755
        {
756
                PTPTRACE2("CaptureImage error", ptp_error);
757
                return ptp_error;
758
        }
759
        PTPUSBEventContainer    evnt;
760
        bool                                    occured;
761
 
762
        // multiple objects can be added depending on current camera shooting mode
763
        while ((occured = EventWait(sizeof(PTPUSBEventContainer), (uint8_t*)&evnt, 500)) && evnt.code == PTP_EC_ObjectAdded)
764
                PTPTRACE("CaptureImage: New object added.\r\n");
765
 
766
        if (!occured)
767
        {
768
                PTPTRACE("CaptureImage: Timeout ellapsed.\r\n");
769
                return PTP_RC_Undefined;
770
        }
771
        switch (evnt.code)
772
        {
773
        case PTP_EC_CaptureComplete:
774
                PTPTRACE("CaptureImage: Image captured.\r\n");
775
                return PTP_RC_OK;
776
 
777
        case PTP_EC_StoreFull:
778
                PTPTRACE("CaptureImage: Storage is full.\r\n");
779
                return PTP_RC_StoreFull;
780
 
781
        default:
782
                PTPTRACE2("CaptureImage: Unexpected event\r\n", evnt.code);
783
                return PTP_RC_Undefined;
784
        }
785
}
786
 
787
uint16_t PTP::GetStorageIDs(PTPReadParser *parser)
788
{
789
        OperFlags       flags = { 0, 0, 0, 1, 1, 0 };
790
        return Transaction(PTP_OC_GetStorageIDs, &flags, NULL, parser);
791
}
792
 
793
uint16_t PTP::GetStorageIDs(uint8_t bufsize, uint8_t *pbuf)
794
{
795
        OperFlags       flags = { 0, 0, 0, 1, 3, 0 };
796
 
797
        flags.dataSize = bufsize;
798
 
799
        return Transaction(PTP_OC_GetStorageIDs, &flags, NULL, pbuf);
800
}
801
 
802
uint16_t PTP::GetObjectHandles(uint32_t storage_id, uint16_t format, uint16_t assoc, PTPReadParser *parser)
803
{
804
        OperFlags       flags = { 3, 0, 0, 1, 1, 0 };
805
        uint32_t        params[3];
806
 
807
        params[0] = storage_id;
808
        params[1] = (uint32_t)format;
809
        params[2] = (uint32_t)assoc;
810
 
811
        return Transaction(PTP_OC_GetObjectHandles, &flags, params, parser);
812
}
813
 
814
void PTP::Task()
815
{
816
    Max.Task();
817
    Usb.Task();
818
 
819
    if( Usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE )
820
        {
821
                idSession = 0;
822
                idTransaction = 0;
823
 
824
                stateMachine->OnDeviceDisconnectedState(this);
825
        }
826
        //wait for addressing state
827
    if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING )
828
        {  
829
                /* Initialize data structures */
830
            epRecord[ 0 ] = *( Usb.getDevTableEntry( 0,0 ));  //copy endpoint 0 parameters
831
 
832
            // Data-In EP
833
            epRecord[ 1 ].epAddr     = epDataIn;
834
            epRecord[ 1 ].Attr       = 0x02;
835
            epRecord[ 1 ].MaxPktSize = 0x0040;
836
            epRecord[ 1 ].Interval   = 0;
837
            epRecord[ 1 ].sndToggle  = bmSNDTOG0;
838
            epRecord[ 1 ].rcvToggle  = bmRCVTOG0;
839
 
840
            // Data-Out EP
841
            epRecord[ 2 ].epAddr     = epDataOut;
842
            epRecord[ 2 ].Attr       = 0x02;
843
            epRecord[ 2 ].MaxPktSize = 0x0040;
844
            epRecord[ 2 ].Interval   = 0;
845
            epRecord[ 2 ].sndToggle  = bmSNDTOG0;
846
            epRecord[ 2 ].rcvToggle  = bmRCVTOG0;
847
 
848
            // Interrupt EP
849
            epRecord[ 3 ].epAddr     = epInterrupt;
850
            epRecord[ 3 ].Attr       = 0x03;
851
            epRecord[ 3 ].MaxPktSize = 0x0008;
852
            epRecord[ 3 ].Interval   = 0x0A;
853
            epRecord[ 3 ].sndToggle  = bmSNDTOG0;
854
            epRecord[ 3 ].rcvToggle  = bmRCVTOG0;
855
 
856
            Usb.setDevTableEntry( devAddress, epRecord );
857
 
858
                uint8_t rcode;
859
 
860
            /* Configure device */
861
            if ((rcode = Usb.setConf( devAddress, 0, numConf )))
862
                HaltOnError(MsgErrDeviceConf, rcode);
863
 
864
        Usb.setUsbTaskState( USB_STATE_RUNNING );
865
 
866
                SetInitialState();
867
        }
868
        if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
869
        {  
870
                Task2();
871
    }
872
}
873
 
874
uint8_t PTP::GetConfDescr( byte addr, byte conf )
875
{
876
        char buf[ PTP_MAX_RX_BUFFER_LEN ];
877
        byte rcode;
878
        unsigned int total_length;
879
        rcode = Usb.getConfDescr( addr, 0, 4, conf, buf );  //get total length
880
        //LOBYTE( total_length ) = buf[ 2 ];
881
        //HIBYTE( total_length ) = buf[ 3 ];
882
 
883
        total_length = *((uint16_t*)(buf + 2));
884
 
885
        if( total_length > PTP_MAX_RX_BUFFER_LEN )
886
        {    //check if total length is larger than buffer
887
                //Serial.println("Total length truncated to 256 bytes");
888
                total_length = PTP_MAX_RX_BUFFER_LEN;
889
        }
890
        rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
891
        return( 0 );
892
}