blob: 718d432e61fdd40fa57c443ec277a2e00b3fed15 [file] [log] [blame]
Damien4b6e85c2013-10-21 09:56:56 +01001#include <string.h>
2
Damienfee89d52013-10-13 19:02:15 +01003#include "usb_core.h"
4#include "usbd_core.h"
Damien4a175e12013-10-17 22:50:21 +01005#include "usbd_cdc_core.h"
Damienfee89d52013-10-13 19:02:15 +01006#include "usbd_pyb_core.h"
Damiened656052013-10-13 00:42:20 +01007#include "usbd_usr.h"
8#include "usbd_desc.h"
Damien4b6e85c2013-10-21 09:56:56 +01009
10#include "misc.h"
Damien Georgeb5d13c32014-01-22 22:55:07 +000011#include "mpconfig.h"
12#include "qstr.h"
13#include "obj.h"
Damien George01156d52014-02-01 16:04:34 +000014#include "pendsv.h"
Damienfb42ec12013-10-19 15:37:09 +010015#include "usb.h"
Damiened656052013-10-13 00:42:20 +010016
Damien Georgeb5d13c32014-01-22 22:55:07 +000017#ifdef USE_DEVICE_MODE
Damien4a175e12013-10-17 22:50:21 +010018extern CDC_IF_Prop_TypeDef VCP_fops;
Damien Georgeb5d13c32014-01-22 22:55:07 +000019#endif
Damiened656052013-10-13 00:42:20 +010020
Damien George75abee22014-01-26 17:41:01 +000021USB_OTG_CORE_HANDLE USB_OTG_Core;
Damien3f69aca2013-10-21 23:46:04 +010022
Damien George75abee22014-01-26 17:41:01 +000023static int dev_is_enabled = 0;
Damien Georged71cd862014-02-01 16:17:06 +000024uint32_t APP_dev_is_connected = 0; /* used by usbd_cdc_vcp */
Damien3f69aca2013-10-21 23:46:04 +010025static char rx_buf[64];
26static int rx_buf_in;
27static int rx_buf_out;
Damien George01156d52014-02-01 16:04:34 +000028static int interrupt_char = VCP_CHAR_NONE;
29mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
Damiened656052013-10-13 00:42:20 +010030
Damien George75abee22014-01-26 17:41:01 +000031void pyb_usb_dev_init(void) {
Damien Georgeb5d13c32014-01-22 22:55:07 +000032#ifdef USE_DEVICE_MODE
Damien George75abee22014-01-26 17:41:01 +000033 if (!dev_is_enabled) {
34 // only init USB once in the device's power-lifetime
35 USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
36 //USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_HID_cb, &USR_cb);
Damiene9f1e502013-10-22 23:09:25 +010037 }
Damien4b6e85c2013-10-21 09:56:56 +010038 rx_buf_in = 0;
39 rx_buf_out = 0;
Damien George01156d52014-02-01 16:04:34 +000040 interrupt_char = VCP_CHAR_NONE;
Damien George75abee22014-01-26 17:41:01 +000041 dev_is_enabled = 1;
Damien George01156d52014-02-01 16:04:34 +000042
43 // create an exception object for interrupting by VCP
Damien Georgec5966122014-02-15 16:10:44 +000044 mp_const_vcp_interrupt = mp_obj_new_exception_msg(&mp_type_OSError, "VCPInterrupt");
Damien George75abee22014-01-26 17:41:01 +000045#endif
Damien4a175e12013-10-17 22:50:21 +010046}
47
Damien0f654512013-10-23 20:39:20 +010048bool usb_vcp_is_enabled(void) {
Damien George75abee22014-01-26 17:41:01 +000049 return dev_is_enabled;
Damien3f69aca2013-10-21 23:46:04 +010050}
51
muxb2269b62014-02-01 13:26:04 +020052bool usb_vcp_is_connected(void) {
Damien Georged71cd862014-02-01 16:17:06 +000053 return APP_dev_is_connected;
54}
55
Damien George01156d52014-02-01 16:04:34 +000056void usb_vcp_set_interrupt_char(int c) {
57 if (dev_is_enabled) {
58 interrupt_char = c;
59 }
60}
61
Damien4b6e85c2013-10-21 09:56:56 +010062void usb_vcp_receive(const char *buf, uint32_t len) {
Damien George75abee22014-01-26 17:41:01 +000063 if (dev_is_enabled) {
Damienf48cf672013-10-21 10:42:06 +010064 for (int i = 0; i < len; i++) {
Damien George01156d52014-02-01 16:04:34 +000065
66 // catch special interrupt character
67 if (buf[i] == interrupt_char) {
68 // raise exception when interrupts are finished
Damien Georgec5966122014-02-15 16:10:44 +000069 mp_obj_exception_clear_traceback(mp_const_vcp_interrupt);
Damien George01156d52014-02-01 16:04:34 +000070 pendsv_nlr_jump(mp_const_vcp_interrupt);
71 interrupt_char = VCP_CHAR_NONE;
72 continue;
73 }
74
Damienf48cf672013-10-21 10:42:06 +010075 rx_buf[rx_buf_in++] = buf[i];
76 if (rx_buf_in >= sizeof(rx_buf)) {
77 rx_buf_in = 0;
78 }
79 if (rx_buf_in == rx_buf_out) {
80 rx_buf_out = rx_buf_in + 1;
81 if (rx_buf_out >= sizeof(rx_buf)) {
82 rx_buf_out = 0;
83 }
Damien4b6e85c2013-10-21 09:56:56 +010084 }
85 }
86 }
87}
88
Damien0f654512013-10-23 20:39:20 +010089int usb_vcp_rx_any(void) {
Damien4b6e85c2013-10-21 09:56:56 +010090 if (rx_buf_in >= rx_buf_out) {
91 return rx_buf_in - rx_buf_out;
92 } else {
93 return rx_buf_in + sizeof(rx_buf) - rx_buf_out;
94 }
95}
96
Damien0f654512013-10-23 20:39:20 +010097char usb_vcp_rx_get(void) {
Damien4b6e85c2013-10-21 09:56:56 +010098 while (rx_buf_out == rx_buf_in) {
99 }
100 char c = rx_buf[rx_buf_out];
101 rx_buf_out += 1;
102 if (rx_buf_out >= sizeof(rx_buf)) {
103 rx_buf_out = 0;
104 }
105 return c;
106}
107
108void usb_vcp_send_str(const char *str) {
109 usb_vcp_send_strn(str, strlen(str));
110}
111
112void usb_vcp_send_strn(const char *str, int len) {
Damien Georgeb5d13c32014-01-22 22:55:07 +0000113#ifdef USE_DEVICE_MODE
Damien George75abee22014-01-26 17:41:01 +0000114 if (dev_is_enabled) {
Damien4b6e85c2013-10-21 09:56:56 +0100115 VCP_fops.pIf_DataTx((const uint8_t*)str, len);
Damien4a175e12013-10-17 22:50:21 +0100116 }
Damien George75abee22014-01-26 17:41:01 +0000117#endif
Damiened656052013-10-13 00:42:20 +0100118}
Damien0c5827f2013-10-22 21:13:36 +0100119
Damien George328708e2014-01-13 00:20:06 +0000120#include "usbd_conf.h"
Damien0c5827f2013-10-22 21:13:36 +0100121
122/* These are external variables imported from CDC core to be used for IN
123 transfer management. */
Damien Georgeb5d13c32014-01-22 22:55:07 +0000124#ifdef USE_DEVICE_MODE
Damien0c5827f2013-10-22 21:13:36 +0100125extern uint8_t APP_Rx_Buffer []; /* Write CDC received data in this buffer.
126 These data will be sent over USB IN endpoint
127 in the CDC core functions. */
128extern uint32_t APP_Rx_ptr_in; /* Increment this pointer or roll it back to
129 start address when writing received data
130 in the buffer APP_Rx_Buffer. */
Damien Georgeb5d13c32014-01-22 22:55:07 +0000131#endif
Damien0c5827f2013-10-22 21:13:36 +0100132
133void usb_vcp_send_strn_cooked(const char *str, int len) {
Damien Georgeb5d13c32014-01-22 22:55:07 +0000134#ifdef USE_DEVICE_MODE
Damien0c5827f2013-10-22 21:13:36 +0100135 for (const char *top = str + len; str < top; str++) {
136 if (*str == '\n') {
137 APP_Rx_Buffer[APP_Rx_ptr_in] = '\r';
138 APP_Rx_ptr_in = (APP_Rx_ptr_in + 1) & (APP_RX_DATA_SIZE - 1);
139 }
140 APP_Rx_Buffer[APP_Rx_ptr_in] = *str;
141 APP_Rx_ptr_in = (APP_Rx_ptr_in + 1) & (APP_RX_DATA_SIZE - 1);
142 }
Damien Georgeb5d13c32014-01-22 22:55:07 +0000143#endif
Damien0c5827f2013-10-22 21:13:36 +0100144}
Damien58a1b4c2013-10-25 20:53:54 +0100145
146void usb_hid_send_report(uint8_t *buf) {
Damien Georgeb5d13c32014-01-22 22:55:07 +0000147#ifdef USE_DEVICE_MODE
Damien George75abee22014-01-26 17:41:01 +0000148 USBD_HID_SendReport(&USB_OTG_Core, buf, 4);
Damien Georgeb5d13c32014-01-22 22:55:07 +0000149#endif
Damien58a1b4c2013-10-25 20:53:54 +0100150}
Damien George328708e2014-01-13 00:20:06 +0000151
152/******************************************************************************/
153// code for experimental USB OTG support
154
155#ifdef USE_HOST_MODE
156
Damien George75abee22014-01-26 17:41:01 +0000157#include "led.h"
158#include "usbh_core.h"
159#include "usbh_usr.h"
160#include "usbh_hid_core.h"
161#include "usbh_hid_keybd.h"
162#include "usbh_hid_mouse.h"
Damien George328708e2014-01-13 00:20:06 +0000163
164__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ;
165
166static int host_is_enabled = 0;
Damien George75abee22014-01-26 17:41:01 +0000167
168void pyb_usb_host_init(void) {
Damien George328708e2014-01-13 00:20:06 +0000169 if (!host_is_enabled) {
170 // only init USBH once in the device's power-lifetime
171 /* Init Host Library */
Damien George75abee22014-01-26 17:41:01 +0000172 USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks);
Damien George328708e2014-01-13 00:20:06 +0000173 }
174 host_is_enabled = 1;
175}
176
Damien George75abee22014-01-26 17:41:01 +0000177void pyb_usb_host_process(void) {
178 USBH_Process(&USB_OTG_Core, &USB_Host);
Damien Georgeb5d13c32014-01-22 22:55:07 +0000179}
180
Damien George75abee22014-01-26 17:41:01 +0000181uint8_t usb_keyboard_key = 0;
182
183// TODO this is an ugly hack to get key presses
184uint pyb_usb_host_get_keyboard(void) {
185 uint key = usb_keyboard_key;
186 usb_keyboard_key = 0;
187 return key;
Damien George328708e2014-01-13 00:20:06 +0000188}
189
Damien George75abee22014-01-26 17:41:01 +0000190void USR_MOUSE_Init(void) {
191 led_state(4, 1);
192 USB_OTG_BSP_mDelay(100);
193 led_state(4, 0);
194}
195
196void USR_MOUSE_ProcessData(HID_MOUSE_Data_TypeDef *data) {
197 led_state(4, 1);
198 USB_OTG_BSP_mDelay(50);
199 led_state(4, 0);
200}
201
202void USR_KEYBRD_Init(void) {
203 led_state(4, 1);
204 USB_OTG_BSP_mDelay(100);
205 led_state(4, 0);
206}
207
208void USR_KEYBRD_ProcessData(uint8_t pbuf) {
209 led_state(4, 1);
210 USB_OTG_BSP_mDelay(50);
211 led_state(4, 0);
212 //lcd_print_strn((char*)&pbuf, 1);
213 usb_keyboard_key = pbuf;
Damien George3257d352014-01-23 22:16:15 +0000214}
215
Damien George328708e2014-01-13 00:20:06 +0000216#endif // USE_HOST_MODE