dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_usb.c
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  */
30 
31 /* Project Includes */
32 #include "pios.h"
33 #include "usb_lib.h"
34 #include "pios_usb_board_data.h"
35 #include "stm32f10x.h"
36 
37 #include "pios_usb.h"
38 #include "pios_usb_priv.h"
39 
40 #if defined(PIOS_INCLUDE_USB_HID)
41 
42 /* Rx/Tx status */
43 static bool transfer_possible = false;
44 
45 /* USB activity detection */
46 static volatile bool sof_seen_since_reset = false;
47 
48 enum pios_usb_dev_magic {
49  PIOS_USB_DEV_MAGIC = 0x17365904,
50 };
51 
52 struct pios_usb_dev {
53  enum pios_usb_dev_magic magic;
54  const struct pios_usb_cfg * cfg;
55 };
56 
61 static int32_t PIOS_USB_validate(struct pios_usb_dev * usb_dev)
62 {
63  if(usb_dev == NULL)
64  return -1;
65 
66  if (usb_dev->magic != PIOS_USB_DEV_MAGIC)
67  return -1;
68 
69  return 0;
70 }
71 
72 static struct pios_usb_dev * PIOS_USB_alloc(void)
73 {
74  struct pios_usb_dev * usb_dev;
75 
76  usb_dev = (struct pios_usb_dev *)PIOS_malloc(sizeof(*usb_dev));
77  if (!usb_dev) return(NULL);
78 
79  usb_dev->magic = PIOS_USB_DEV_MAGIC;
80  return(usb_dev);
81 }
82 
88 static uintptr_t pios_usb_com_id;
89 int32_t PIOS_USB_Init(uintptr_t * usb_id, const struct pios_usb_cfg * cfg)
90 {
91  PIOS_Assert(usb_id);
92  PIOS_Assert(cfg);
93 
94  struct pios_usb_dev * usb_dev;
95 
96  usb_dev = (struct pios_usb_dev *) PIOS_USB_alloc();
97  if (!usb_dev) goto out_fail;
98 
99  /* Bind the configuration to the device instance */
100  usb_dev->cfg = cfg;
101 
103 
104  /*
105  * This is a horrible hack to make this available to
106  * the interrupt callbacks. This should go away ASAP.
107  */
108  pios_usb_com_id = (uintptr_t) usb_dev;
109 
110  /* Enable the USB Interrupts */
111  NVIC_Init((NVIC_InitTypeDef*)&usb_dev->cfg->irq.init);
112 
113  /* Select USBCLK source */
114  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
115  /* Enable the USB clock */
116  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
117 
118  USB_Init();
119  USB_SIL_Init();
120 
121  *usb_id = (uintptr_t) usb_dev;
122 
123  return 0; /* No error */
124 
125 out_fail:
126  return(-1);
127 }
128 
135 int32_t PIOS_USB_ChangeConnectionState(bool Connected)
136 {
137  // In all cases: re-initialise USB HID driver
138  if (Connected) {
139  transfer_possible = true;
140 
141  //TODO: Check SetEPRxValid(ENDP1);
142 
143 #if defined(USB_LED_ON)
144  USB_LED_ON; // turn the USB led on
145 #endif
146  } else {
147  // Cable disconnected: disable transfers
148  transfer_possible = false;
149 
150 #if defined(USB_LED_OFF)
151  USB_LED_OFF; // turn the USB led off
152 #endif
153  }
154 
155  return 0;
156 }
157 
158 int32_t PIOS_USB_Reenumerate()
159 {
160  /* Force USB reset and power-down (this will also release the USB pins for direct GPIO control) */
161  _SetCNTR(CNTR_FRES | CNTR_PDWN);
162 
163  /* Using a "dirty" method to force a re-enumeration: */
164  /* Force DPM (Pin PA12) low for ca. 10 mS before USB Tranceiver will be enabled */
165  /* This overrules the external Pull-Up at PA12, and at least Windows & MacOS will enumerate again */
166  GPIO_InitTypeDef GPIO_InitStructure;
167  GPIO_StructInit(&GPIO_InitStructure);
168  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
169  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
170  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
171  GPIO_Init(GPIOA, &GPIO_InitStructure);
172 
173  PIOS_DELAY_WaitmS(50);
174 
175  /* Release power-down, still hold reset */
176  _SetCNTR(CNTR_PDWN);
178 
179  /* CNTR_FRES = 0 */
180  _SetCNTR(0);
181 
182  /* Clear pending interrupts */
183  _SetISTR(0);
184 
185  /* Configure USB clock */
186  /* USBCLK = PLLCLK / 1.5 */
187  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
188  /* Enable USB clock */
189  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
190 
191  return 0;
192 }
193 
194 bool PIOS_USB_CableConnected(uintptr_t id)
195 {
196  struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id;
197 
198  if (PIOS_USB_validate(usb_dev) != 0)
199  return false;
200 
201  if (usb_dev->cfg->vsense.gpio != NULL)
202  return GPIO_ReadInputDataBit(usb_dev->cfg->vsense.gpio, usb_dev->cfg->vsense.init.GPIO_Pin) == Bit_SET;
203 
204  return sof_seen_since_reset;
205 }
206 
207 bool PIOS_USB_HaveVSense(uintptr_t id)
208 {
209  struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id;
210 
211  if (PIOS_USB_validate(usb_dev) != 0)
212  return false;
213 
214  return usb_dev->cfg->vsense.gpio != NULL;
215 }
216 
223 bool PIOS_USB_CheckAvailable(uintptr_t id)
224 {
225  struct pios_usb_dev * usb_dev = (struct pios_usb_dev *) pios_usb_com_id;
226 
227  if (PIOS_USB_validate(usb_dev) != 0)
228  return false;
229 
230  return PIOS_USB_CableConnected(id) && transfer_possible;
231 }
232 
233 void SOF_Callback(void)
234 {
235  sof_seen_since_reset = true;
236 }
237 
238 void SUSP_Callback(void)
239 {
240  sof_seen_since_reset = false;
241 }
242 
243 #endif
244 
Main PiOS header to include all the compiled in PiOS options.
int32_t PIOS_USB_Reenumerate()
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_USB_CheckAvailable(uintptr_t id)
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
#define USB_LED_OFF
Definition: pios_board.h:103
USB private definitions.
int32_t PIOS_USB_ChangeConnectionState(bool connected)
USB HID layer functions header.
uint32_t magic
bool PIOS_USB_HaveVSense(uintptr_t id)
int32_t PIOS_USB_Init(uintptr_t *usb_id, const struct pios_usb_cfg *cfg)
#define USB_LED_ON
Definition: pios_board.h:102
bool PIOS_USB_CableConnected(uintptr_t id)
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t PIOS_DELAY_WaitmS(uint32_t mS)
Definition: pios_delay.c:140
int32_t PIOS_DELAY_WaituS(uint32_t uS)
Definition: pios_delay.c:116