aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_usbhost.h
blob: b289a896efeaf5bc9bd1f1132468435a0cdcd18a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
/* Copyright (C) 2015-2016 Andrew J. Kroll
   and
Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Contact information
-------------------

Circuits At Home, LTD
Web      :  https://www.circuitsathome.com
e-mail   :  support@circuitsathome.com
 */

#ifndef _UHS_host_h_
#error "Never include UHS_usbhost.h directly; include UHS_host.h instead"
#else
#ifndef _USBHOST_H_
#define _USBHOST_H_

// Very early prototypes
#ifdef UHS_LOAD_BT
void UHS_BT_SetUSBInterface(UHS_USB_HOST_BASE *host, ENUMERATION_INFO *ei);
void UHS_BT_ScanUninitialized(UHS_USB_HOST_BASE *host);
void UHS_BT_Poll(UHS_USB_HOST_BASE *host);
#endif
#ifdef UHS_LOAD_HID
void UHS_HID_SetUSBInterface(UHS_USB_HOST_BASE *host, ENUMERATION_INFO *ei);
void UHS_HID_ScanUninitialized(UHS_USB_HOST_BASE *host);
void UHS_HID_Poll(UHS_USB_HOST_BASE *host);
#endif

//#if defined(LOAD_UHS_CDC_ACM) || defined(LOAD_UHS_CDC_ACM_FTDI) || defined(LOAD_UHS_CDC_ACM_PROLIFIC) || defined(LOAD_UHS_CDC_ACM_XR21B1411)
//void UHS_CDC_ACM_SetUSBInterface(UHS_USB_HOST_BASE *host, ENUMERATION_INFO *ei);
//void UHS_CDC_ACM_ScanUninitialized(UHS_USB_HOST_BASE *host);
//void UHS_CDC_ACM_Poll(UHS_USB_HOST_BASE *host);
//#endif

class UHS_USBInterface; // forward class declaration

// enumerator to turn the VBUS on/off

typedef enum {
        vbus_on = 0,
        vbus_off = 1
} VBUS_t;

// All host SEI use this base class

class UHS_USB_HOST_BASE {
public:
        AddressPool addrPool;
        UHS_USBInterface* devConfig[UHS_HOST_MAX_INTERFACE_DRIVERS];
        volatile uint8_t usb_error;
        volatile uint8_t usb_task_state;
        volatile uint8_t usb_task_polling_disabled;
        volatile uint8_t usb_host_speed;
        volatile uint8_t hub_present;

        UHS_USB_HOST_BASE() {
                for(uint16_t i = 0; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) {
                        devConfig[i] = NULL;
                }
                usb_task_polling_disabled = 0;
                usb_task_state = UHS_USB_HOST_STATE_INITIALIZE; //set up state machine
                usb_host_speed = 0;
                usb_error = 0;
        };

        /////////////////////////////////////////////
        //
        // Virtual methods that interface to the SIE
        // Overriding each is mandatory.
        //
        /////////////////////////////////////////////

        /**
         * Delay for x milliseconds
         * Override if your controller provides an SOF IRQ, which may involve
         * some sort of reentrant ISR or workaround with interrupts enabled.
         *
         * @param x how many milliseconds to delay
         * @return true if delay completed without a state change, false if delay aborted
         */
        virtual bool UHS_NI sof_delay(uint16_t x) {
                if(!(usb_task_state & UHS_USB_HOST_STATE_MASK)) return false;
                uint8_t current_state = usb_task_state;
                while(current_state == usb_task_state && x--) {
                        delay(1);
                }
                return (current_state == usb_task_state);
        };

        virtual UHS_EpInfo * UHS_NI ctrlReqOpen(NOTUSED(uint8_t addr), NOTUSED(uint64_t Request), NOTUSED(uint8_t* dataptr)) {
                return NULL;
        };

        virtual void UHS_NI vbusPower(NOTUSED(VBUS_t state)) {
        };

        virtual void UHS_NI Task() {
        };

        virtual uint8_t UHS_NI SetAddress(NOTUSED(uint8_t addr), NOTUSED(uint8_t ep), NOTUSED(UHS_EpInfo **ppep), NOTUSED(uint16_t &nak_limit)) {
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual uint8_t UHS_NI OutTransfer(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint16_t nak_limit), NOTUSED(uint16_t nbytes), NOTUSED(uint8_t *data)) {
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual uint8_t UHS_NI InTransfer(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint16_t nak_limit), NOTUSED(uint16_t *nbytesptr), NOTUSED(uint8_t *data)) {
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual uint8_t UHS_NI ctrlReqClose(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint8_t bmReqType), NOTUSED(uint16_t left), NOTUSED(uint16_t nbytes), NOTUSED(uint8_t *dataptr)) {
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual uint8_t UHS_NI ctrlReqRead(NOTUSED(UHS_EpInfo *pep), NOTUSED(uint16_t *left), NOTUSED(uint16_t *read), NOTUSED(uint16_t nbytes), NOTUSED(uint8_t *dataptr)) {
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual uint8_t UHS_NI dispatchPkt(NOTUSED(uint8_t token), NOTUSED(uint8_t ep), NOTUSED(uint16_t nak_limit)) {
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual uint8_t UHS_NI init() {
                return 0;
        };

        virtual void UHS_NI doHostReset() {
        };

        virtual int16_t UHS_NI Init(NOTUSED(int16_t mseconds)) {
                return -1;
        };

        virtual int16_t UHS_NI Init() {
                return Init(INT16_MIN);
        };

        virtual uint8_t hwlPowerUp() {
                /* This is for machine specific support to enable/power up the USB HW to operate*/
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual uint8_t hwPowerDown() {
                /* This is for machine specific support to disable/powerdown the USB Hw */
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        virtual bool IsHub(uint8_t klass) {
                return (klass == UHS_USB_CLASS_HUB);
        };

        virtual void UHS_NI suspend_host() {
                // Used on MCU that lack control of IRQ priority (AVR).
                // Suspends ISRs, for critical code. IRQ will be serviced after it is resumed.
                // NOTE: you must track the state yourself!
        };

        virtual void UHS_NI resume_host() {
                // Used on MCU that lack control of IRQ priority (AVR).
                // Resumes ISRs.
                // NOTE: you must track the state yourself!
        };

        /////////////////////////////////////////////
        //
        // Built-ins, No need to override
        //
        /////////////////////////////////////////////
        // these two probably will go away, and won't be used, TBD
        inline void Poll_Others() {
#ifdef UHS_LOAD_BT
                UHS_BT_Poll(this);
#endif
#ifdef UHS_LOAD_HID
                UHS_HID_Poll(this);
#endif
        }

        inline void DisablePoll() {
                noInterrupts();
                usb_task_polling_disabled++;
                DDSB();
                interrupts();
        }

        inline void EnablePoll() {
                noInterrupts();
                usb_task_polling_disabled--;
                DDSB();
                interrupts();
        }

        uint8_t UHS_NI seekInterface(ENUMERATION_INFO *ei, uint16_t inf, USB_FD_CONFIGURATION_DESCRIPTOR *ucd);

        uint8_t UHS_NI setEpInfoEntry(uint8_t addr, uint8_t iface, uint8_t epcount, volatile UHS_EpInfo* eprecord_ptr);

        uint8_t UHS_NI EPClearHalt(uint8_t addr, uint8_t ep);

        uint8_t UHS_NI ctrlReq(uint8_t addr, uint64_t Request, uint16_t nbytes, uint8_t* dataptr);

        uint8_t UHS_NI getDevDescr(uint8_t addr, uint16_t nbytes, uint8_t* dataptr);

        uint8_t UHS_NI getConfDescr(uint8_t addr, uint16_t nbytes, uint8_t conf, uint8_t* dataptr);

        uint8_t UHS_NI setAddr(uint8_t oldaddr, uint8_t newaddr);

        uint8_t UHS_NI setConf(uint8_t addr, uint8_t conf_value);

        uint8_t UHS_NI getStrDescr(uint8_t addr, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr);

        void UHS_NI ReleaseDevice(uint8_t addr);

        uint8_t UHS_NI Configuring(uint8_t parent, uint8_t port, uint8_t speed);

        void UHS_NI DeviceDefaults(uint8_t maxep, UHS_USBInterface *device);

        UHS_EpInfo* UHS_NI getEpInfoEntry(uint8_t addr, uint8_t ep);

        inline uint8_t getUsbTaskState() {
                return ( usb_task_state);
        };

        inline AddressPool* GetAddressPool() {
                return &addrPool;
        };

        int UHS_NI RegisterDeviceClass(UHS_USBInterface *pdev) {
                for(uint8_t i = 0; i < UHS_HOST_MAX_INTERFACE_DRIVERS; i++) {
                        if(!devConfig[i]) {
                                devConfig[i] = pdev;
                                return i;
                        }
                }
                //return UHS_HOST_ERROR_CANT_REGISTER_DEVICE_CLASS;
                return -1;
        };
#if 0

        inline void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
                addrPool.ForEachUsbDevice(pfunc);
        };
#endif

        uint8_t TestInterface(ENUMERATION_INFO *ei);
        uint8_t enumerateInterface(ENUMERATION_INFO *ei);
        uint8_t getNextInterface(ENUMERATION_INFO *ei, UHS_EpInfo *pep, uint8_t data[], uint16_t *left, uint16_t *read, uint8_t *offset);
        uint8_t initDescrStream(ENUMERATION_INFO *ei, USB_FD_CONFIGURATION_DESCRIPTOR *ucd, UHS_EpInfo *pep, uint8_t *data, uint16_t *left, uint16_t *read, uint8_t *offset);
        uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data);
        uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data);
        uint8_t doSoftReset(uint8_t parent, uint8_t port, uint8_t address);
        uint8_t getone(UHS_EpInfo *pep, uint16_t *left, uint16_t *read, uint8_t *dataptr, uint8_t *offset);
        uint8_t eat(UHS_EpInfo *pep, uint16_t *left, uint16_t *read, uint8_t *dataptr, uint8_t *offset, uint16_t *yum);

};

// All device interface drivers use this subclass

class UHS_USBInterface {
public:

        UHS_USB_HOST_BASE *pUsb; // Parent USB host
        volatile uint8_t bNumEP; // total number of EP in this interface
        volatile UHS_EpInfo epInfo[16]; // This is a stub, override in the driver.

        volatile uint8_t bAddress; // address of the device
        volatile uint8_t bConfNum; // configuration number
        volatile uint8_t bIface; // interface value
        volatile bool bPollEnable; // poll enable flag, operating status
        volatile uint32_t qNextPollTime; // next poll time

        /**
         * Resets interface driver to unused state. You should override this in
         * your driver if it requires extra class variable cleanup.
         */
        virtual void DriverDefaults() {
                printf("Default driver defaults.\r\n");
                pUsb->DeviceDefaults(bNumEP, this);
        };

        /**
         * Checks if this interface is supported.
         * Executed called when new devices are connected.
         *
         * @param ei
         * @return true if the interface is supported
         */
        virtual bool OKtoEnumerate(NOTUSED(ENUMERATION_INFO *ei)) {
                return false;
        };

        /**
         * Configures any needed endpoint information for an interface.
         * You must provide this in your driver.
         * Executed when new devices are connected and OKtoEnumerate()
         * returned true.
         *
         * @param ei
         * @return zero on success
         */
        virtual uint8_t SetInterface(NOTUSED(ENUMERATION_INFO *ei)) {
                return UHS_HOST_ERROR_NOT_IMPLEMENTED;
        };

        /**
         * Interface specific additional setup and enumeration that
         * can't occur when the descriptor stream is open.
         * Also used for collection of unclaimed interfaces, to link to the master.
         *
         * @return zero on success
         */
        virtual uint8_t Finalize() {
                return 0;
        };

        /**
         *  Executed after interface is finalized but, before polling has started.
         *
         * @return 0 on success
         */
        virtual uint8_t OnStart() {
                return 0;
        };

        /**
         * Start interface polling
         * @return
         */
        virtual uint8_t Start() {
                uint8_t rcode = OnStart();
                if(!rcode) bPollEnable = true;
                return rcode;
        };

        /**
         * Executed before anything else in Release().
         */
        virtual void OnRelease() {
                return;
        };

        /**
         * Release resources when device is disconnected.
         * Normally this does not need to be overridden.
         */
        virtual void Release() {
                OnRelease();
                DriverDefaults();
                return;
        };

        /**
         * Executed After driver polls.
         * Can be used when there is an important change detected during polling
         * and you want to handle it elsewhere.
         * Examples:
         * Media status change for bulk, e.g. ready, not-ready, media changed, door opened.
         * Button state/joystick position/etc changes on a HID device.
         * Flow control status change on a communication device, e.g. CTS on serial
         */
        virtual void OnPoll() {
                return;
        };

        /**
         * Poll interface driver. You should override this in your driver if you
         * require polling faster or slower than every 100 milliseconds, or your
         * driver requires special housekeeping.
         */
        virtual void Poll() {
                OnPoll();
                qNextPollTime = millis() + 100;
        };

        virtual bool UHS_NI Polling() {
                return bPollEnable;
        }

        /**
         * This is only for a hub.
         * @param port
         */
        virtual void ResetHubPort(NOTUSED(uint8_t port)) {
                return;
        };

#if 0
        /**
         * @return true if this interface is Vendor Specific.
         */
        virtual bool IsVSI() {
                return false;
        }
#endif
};

#if 0
/**
 * Vendor Specific interface class.
 * This is used by a partner interface.
 * It can also be used to force-enumerate an interface that
 * can use this interface directly.
 * You can also add an instance of this class within the interface constructor
 * if you expect the interface.
 *
 * If this is not needed, it may be removed. Nothing I have written needs this.
 * Let me know if it is not required, then IsVSI method can also be shit-canned.
 * -- AJK
 */

class UHS_VSI : public UHS_USBInterface {
public:
        volatile UHS_EpInfo epInfo[1];
        volatile ENUMERATION_INFO eInfo;
        UHS_VSI(UHS_USB_HOST_BASE *p);
        bool OKtoEnumerate(ENUMERATION_INFO *ei);
        uint8_t SetInterface(ENUMERATION_INFO *ei);
        virtual void DriverDefaults();
        virtual void Release();

        uint8_t GetAddress() {
                return bAddress;
        };

        virtual bool IsVSI() {
                return true;
        }

};
#endif

#endif //_USBHOST_H_
#endif