USB Host Shield 2.0
AMBX.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2021 Aran Vink. 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  Aran Vink
14  e-mail : aranvink@gmail.com
15  */
16 
17 #include "AMBX.h"
18 // To enable serial debugging see "settings.h"
19 //#define EXTRADEBUG // Uncomment to get even more debugging data
20 
22 pUsb(p), // pointer to USB class instance - mandatory
23 bAddress(0) // device address - mandatory
24 {
25  for(uint8_t i = 0; i < AMBX_MAX_ENDPOINTS; i++) {
26  epInfo[i].epAddr = 0;
27  epInfo[i].maxPktSize = (i) ? 0 : 8;
28  epInfo[i].bmSndToggle = 0;
29  epInfo[i].bmRcvToggle = 0;
31  }
32 
33  if(pUsb) // register in USB subsystem
34  pUsb->RegisterDeviceClass(this); //set devConfig[] entry
35 }
36 
37 uint8_t AMBX::Init(uint8_t parent, uint8_t port, bool lowspeed) {
38  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
39  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
40  uint8_t rcode;
41  UsbDevice *p = NULL;
42  EpInfo *oldep_ptr = NULL;
43  uint16_t PID;
44  uint16_t VID;
45 
46  // get memory address of USB device address pool
47  AddressPool &addrPool = pUsb->GetAddressPool();
48 #ifdef EXTRADEBUG
49  Notify(PSTR("\r\nAMBX Init"), 0x80);
50 #endif
51  // check if address has already been assigned to an instance
52  if(bAddress) {
53 #ifdef DEBUG_USB_HOST
54  Notify(PSTR("\r\nAddress in use"), 0x80);
55 #endif
57  }
58 
59  // Get pointer to pseudo device with address 0 assigned
60  p = addrPool.GetUsbDevicePtr(0);
61 
62  if(!p) {
63 #ifdef DEBUG_USB_HOST
64  Notify(PSTR("\r\nAddress not found"), 0x80);
65 #endif
67  }
68 
69  if(!p->epinfo) {
70 #ifdef DEBUG_USB_HOST
71  Notify(PSTR("\r\nepinfo is null"), 0x80);
72 #endif
74  }
75 
76  // Save old pointer to EP_RECORD of address 0
77  oldep_ptr = p->epinfo;
78 
79  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
80  p->epinfo = epInfo;
81 
82  p->lowspeed = lowspeed;
83 
84  // Get device descriptor
85  rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
86  // Restore p->epinfo
87  p->epinfo = oldep_ptr;
88 
89  if(rcode)
90  goto FailGetDevDescr;
91 
92  VID = udd->idVendor;
93  PID = udd->idProduct;
94 
95  if(VID != AMBX_VID || (PID != AMBX_PID))
96  goto FailUnknownDevice;
97 
98  // Allocate new address according to device class
99  bAddress = addrPool.AllocAddress(parent, false, port);
100 
101  if(!bAddress)
103 
104  // Extract Max Packet Size from device descriptor
105  epInfo[0].maxPktSize = udd->bMaxPacketSize0;
106 
107  // Assign new address to the device
108  rcode = pUsb->setAddr(0, 0, bAddress);
109  if(rcode) {
110  p->lowspeed = false;
111  addrPool.FreeAddress(bAddress);
112  bAddress = 0;
113 #ifdef DEBUG_USB_HOST
114  Notify(PSTR("\r\nsetAddr: "), 0x80);
115  D_PrintHex<uint8_t > (rcode, 0x80);
116 #endif
117  return rcode;
118  }
119 #ifdef EXTRADEBUG
120  Notify(PSTR("\r\nAddr: "), 0x80);
121  D_PrintHex<uint8_t > (bAddress, 0x80);
122 #endif
123 
124  p->lowspeed = false;
125 
126  //get pointer to assigned address record
127  p = addrPool.GetUsbDevicePtr(bAddress);
128  if(!p)
130 
131  p->lowspeed = lowspeed;
132 
133  // Assign epInfo to epinfo pointer - only EP0 is known
134  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
135  if(rcode)
136  goto FailSetDevTblEntry;
137 
138 
139  /* The application will work in reduced host mode, so we can save program and data
140  memory space. After verifying the PID and VID we will use known values for the
141  configuration values for device, interface, endpoints for the AMBX Controller */
142 
143  /* Initialize data structures for endpoints of device */
144  epInfo[ AMBX_OUTPUT_PIPE ].epAddr = AMBX_ENDPOINT_OUT; // AMBX output endpoint
146  epInfo[ AMBX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
150 
151  rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
152  if(rcode)
153  goto FailSetDevTblEntry;
154 
155  delay(200); //Give time for address change
156 
157  //For some reason this is need to make it work
158  rcode = pUsb->setConf(bAddress, epInfo[ AMBX_CONTROL_PIPE ].epAddr, 1);
159  if(rcode)
160  goto FailSetConfDescr;
161 
162  if(PID == AMBX_PID || PID) {
163  AMBXConnected = true;
164  }
165  onInit();
166 
167  Notify(PSTR("\r\n"), 0x80);
168  return 0; // Successful configuration
169 
170  /* Diagnostic messages */
171 FailGetDevDescr:
172 #ifdef DEBUG_USB_HOST
174  goto Fail;
175 #endif
176 
177 FailSetDevTblEntry:
178 #ifdef DEBUG_USB_HOST
180  goto Fail;
181 #endif
182 
183 FailSetConfDescr:
184 #ifdef DEBUG_USB_HOST
186 #endif
187  goto Fail;
188 
189 FailUnknownDevice:
190 #ifdef DEBUG_USB_HOST
191  NotifyFailUnknownDevice(VID, PID);
192 #endif
194 
195 Fail:
196 #ifdef DEBUG_USB_HOST
197  Notify(PSTR("\r\nAMBX Init Failed, error code: "), 0x80);
198  NotifyFail(rcode);
199 #endif
200  Release();
201  return rcode;
202 }
203 
204 /* Performs a cleanup after failed Init() attempt */
205 uint8_t AMBX::Release() {
206  AMBXConnected = false;
208  bAddress = 0;
209  return 0;
210 }
211 
212 uint8_t AMBX::Poll() {
213  return 0;
214 }
215 
216 void AMBX::Light_Command(uint8_t *data, uint16_t nbytes) {
217  #ifdef DEBUG_USB_HOST
218  Notify(PSTR("\r\nLight command "), 0x80);
219  #endif
220  pUsb->outTransfer(bAddress, epInfo[ AMBX_OUTPUT_PIPE ].epAddr, nbytes, data);
221 }
222 
223 void AMBX::setLight(uint8_t ambx_light, uint8_t r, uint8_t g, uint8_t b) {
224  writeBuf[0] = AMBX_PREFIX_COMMAND;
225  writeBuf[1] = ambx_light;
226  writeBuf[2] = AMBX_SET_COLOR_COMMAND;
227  writeBuf[3] = r;
228  writeBuf[4] = g;
229  writeBuf[5] = b;
230  Light_Command(writeBuf, AMBX_LIGHT_COMMAND_BUFFER_SIZE);
231 }
232 
233 void AMBX::setLight(AmbxLightsEnum ambx_light, AmbxColorsEnum color) { // Use this to set the Light with Color using the predefined in "AMBXEnums.h"
234  setLight(ambx_light, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
235 }
236 
237 void AMBX::setAllLights(AmbxColorsEnum color) { // Use this to set the Color using the predefined colors in "AMBXEnums.h"
238  setLight(Sidelight_left, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
239  setLight(Sidelight_right, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
240  setLight(Wallwasher_center, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
241  setLight(Wallwasher_left, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
242  setLight(Wallwasher_right, (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
243 }
244 
245 void AMBX::onInit() {
246  #ifdef DEBUG_USB_HOST
247  Notify(PSTR("\r\nOnInit execute "), 0x80);
248  #endif
249  if(pFuncOnInit)
250  pFuncOnInit(); // Call the user function
251 }
AMBX_PID
#define AMBX_PID
Definition: AMBX.h:33
USB::outTransfer
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition: Usb.cpp:303
AddressPool::GetUsbDevicePtr
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
AMBX.h
AMBX_VID
#define AMBX_VID
Definition: AMBX.h:32
AddressPool
Definition: address.h:90
EpInfo::bmSndToggle
uint8_t bmSndToggle
Definition: address.h:47
NotifyFail
#define NotifyFail(...)
Definition: message.h:62
UsbDevice::lowspeed
bool lowspeed
Definition: address.h:86
USB_TRANSFER_TYPE_INTERRUPT
#define USB_TRANSFER_TYPE_INTERRUPT
Definition: usb_ch9.h:93
USB::RegisterDeviceClass
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:230
AddressPool::AllocAddress
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:98
AmbxColorsEnum
AmbxColorsEnum
Definition: AMBXEnums.h:21
NotifyFailSetDevTblEntry
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:58
USB::getDevDescr
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:801
Sidelight_right
@ Sidelight_right
Definition: AMBXEnums.h:32
AmbxLightsEnum
AmbxLightsEnum
Definition: AMBXEnums.h:30
AMBX::setLight
void setLight(uint8_t ambx_light, uint8_t r, uint8_t g, uint8_t b)
Definition: AMBX.cpp:223
AMBX_SET_COLOR_COMMAND
#define AMBX_SET_COLOR_COMMAND
Definition: AMBX.h:42
EpInfo::epAddr
uint8_t epAddr
Definition: address.h:40
AMBX::Poll
uint8_t Poll()
Definition: AMBX.cpp:212
Notify
#define Notify(...)
Definition: message.h:51
Wallwasher_right
@ Wallwasher_right
Definition: AMBXEnums.h:35
AMBX::AMBX
AMBX(USB *pUsb)
Definition: AMBX.cpp:21
NotifyFailGetDevDescr
#define NotifyFailGetDevDescr(...)
Definition: message.h:57
USB_DEVICE_DESCRIPTOR
Definition: usb_ch9.h:105
EpInfo::bmNakPower
uint8_t bmNakPower
Definition: address.h:49
AMBX::pUsb
USB * pUsb
Definition: AMBX.h:140
AMBX_PREFIX_COMMAND
#define AMBX_PREFIX_COMMAND
Definition: AMBX.h:41
USB_NAK_MAX_POWER
#define USB_NAK_MAX_POWER
Definition: address.h:34
AMBX_EP_MAXPKTSIZE
#define AMBX_EP_MAXPKTSIZE
Definition: AMBX.h:24
EpInfo
Definition: address.h:39
AMBX_LIGHT_COMMAND_BUFFER_SIZE
#define AMBX_LIGHT_COMMAND_BUFFER_SIZE
Definition: AMBX.h:53
USB_NAK_NOWAIT
#define USB_NAK_NOWAIT
Definition: address.h:36
EpInfo::bmRcvToggle
uint8_t bmRcvToggle
Definition: address.h:48
AMBX_MAX_ENDPOINTS
#define AMBX_MAX_ENDPOINTS
Definition: AMBX.h:56
Wallwasher_left
@ Wallwasher_left
Definition: AMBXEnums.h:33
NotifyFailUnknownDevice
#define NotifyFailUnknownDevice(...)
Definition: message.h:61
AMBX::epInfo
EpInfo epInfo[AMBX_MAX_ENDPOINTS]
Definition: AMBX.h:144
USB
Definition: UsbCore.h:210
EpInfo::epAttribs
uint8_t epAttribs
Definition: address.h:44
Wallwasher_center
@ Wallwasher_center
Definition: AMBXEnums.h:34
AMBX::setAllLights
void setAllLights(AmbxColorsEnum color)
Definition: AMBX.cpp:237
USB_ERROR_EPINFO_IS_NULL
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:96
AMBX::AMBXConnected
bool AMBXConnected
Definition: AMBX.h:133
UsbDevice
Definition: address.h:82
USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:95
USB::setConf
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:845
AMBX_CONTROL_PIPE
#define AMBX_CONTROL_PIPE
Definition: AMBX.h:27
AMBX_ENDPOINT_OUT
#define AMBX_ENDPOINT_OUT
Definition: AMBX.h:37
PSTR
#define PSTR(str)
Definition: version_helper.h:54
USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:93
NotifyFailSetConfDescr
#define NotifyFailSetConfDescr(...)
Definition: message.h:60
AMBX::Release
uint8_t Release()
Definition: AMBX.cpp:205
AddressPool::FreeAddress
virtual void FreeAddress(uint8_t addr)=0
USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:90
USB::setAddr
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:836
EpInfo::maxPktSize
uint8_t maxPktSize
Definition: address.h:41
AMBX_OUTPUT_PIPE
#define AMBX_OUTPUT_PIPE
Definition: AMBX.h:28
USB::setEpInfoEntry
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition: Usb.cpp:64
AMBX::Init
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: AMBX.cpp:37
Sidelight_left
@ Sidelight_left
Definition: AMBXEnums.h:31
AMBX::bAddress
uint8_t bAddress
Definition: AMBX.h:142
USB::GetAddressPool
AddressPool & GetAddressPool()
Definition: UsbCore.h:226
UsbDevice::epinfo
EpInfo * epinfo
Definition: address.h:83