aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmaple/usb/usb_cdcacm.c402
1 files changed, 202 insertions, 200 deletions
diff --git a/libmaple/usb/usb_cdcacm.c b/libmaple/usb/usb_cdcacm.c
index 46d56bb..d2f6eba 100644
--- a/libmaple/usb/usb_cdcacm.c
+++ b/libmaple/usb/usb_cdcacm.c
@@ -66,13 +66,25 @@
"best."
#endif
+static void vcomDataTxCb(void);
+static void vcomDataRxCb(void);
+static uint8* vcomGetSetLineCoding(uint16);
+
+static void usbInit(void);
+static void usbReset(void);
+static RESULT usbDataSetup(uint8 request);
+static RESULT usbNoDataSetup(uint8 request);
+static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting);
+static uint8* usbGetDeviceDescriptor(uint16 length);
+static uint8* usbGetConfigDescriptor(uint16 length);
+static uint8* usbGetStringDescriptor(uint16 length);
+static void usbSetConfiguration(void);
+static void usbSetDeviceAddress(void);
+
/*
* VCOM config
*/
-#define VCOM_ID_VENDOR 0x1EAF
-#define VCOM_ID_PRODUCT 0x0004
-
#define VCOM_CTRL_EPNUM 0x00
#define VCOM_CTRL_RX_ADDR 0x40
#define VCOM_CTRL_TX_ADDR 0x80
@@ -94,8 +106,9 @@
#define VCOM_RX_EPSIZE 0x40
#define VCOM_RX_BUFLEN (VCOM_RX_EPSIZE*3)
-#define USB_DEVICE_CLASS_CDC 0x02
-#define USB_DEVICE_SUBCLASS_CDC 0x00
+/*
+ * CDC ACM Requests
+ */
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
@@ -104,25 +117,14 @@
#define CONTROL_LINE_DTR (0x01)
#define CONTROL_LINE_RTS (0x02)
-typedef struct {
- uint32 bitrate;
- uint8 format;
- uint8 paritytype;
- uint8 datatype;
-} USB_Line_Coding;
-
-typedef enum {
- DTR_UNSET,
- DTR_HIGH,
- DTR_NEGEDGE,
- DTR_LOW
-} RESET_STATE;
-
-/* Some forward-declared callbacks */
-void vcomDataTxCb(void);
-void vcomDataRxCb(void);
-void vcomManagementCb(void);
+/*
+ * Descriptors
+ */
+#define USB_DEVICE_CLASS_CDC 0x02
+#define USB_DEVICE_SUBCLASS_CDC 0x00
+#define LEAFLABS_ID_VENDOR 0x1EAF
+#define MAPLE_ID_PRODUCT 0x0004
const USB_Descriptor_Device usbVcomDescriptor_Device = {
.bLength = sizeof(USB_Descriptor_Device),
.bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE,
@@ -131,8 +133,8 @@ const USB_Descriptor_Device usbVcomDescriptor_Device = {
.bDeviceSubClass = USB_DEVICE_SUBCLASS_CDC,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = 0x40,
- .idVendor = VCOM_ID_VENDOR,
- .idProduct = VCOM_ID_PRODUCT,
+ .idVendor = LEAFLABS_ID_VENDOR,
+ .idProduct = MAPLE_ID_PRODUCT,
.bcdDevice = 0x0200,
.iManufacturer = 0x01,
.iProduct = 0x02,
@@ -289,15 +291,31 @@ ONE_DESCRIPTOR String_Descriptor[3] = {
{(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(8)}
};
-uint8 last_request = 0;
+/*
+ * Etc.
+ */
+typedef enum {
+ DTR_UNSET,
+ DTR_HIGH,
+ DTR_NEGEDGE,
+ DTR_LOW
+} RESET_STATE;
+
+typedef struct {
+ uint32 bitrate;
+ uint8 format;
+ uint8 paritytype;
+ uint8 datatype;
+} USB_Line_Coding;
+
+uint8 last_request = 0;
USB_Line_Coding line_coding = {
.bitrate = 115200,
.format = 0x00, /* stop bits-1 */
.paritytype = 0x00,
.datatype = 0x08
};
-
uint8 vcomBufferRx[VCOM_RX_BUFLEN];
volatile uint32 countTx = 0;
volatile uint32 recvBufIn = 0;
@@ -307,9 +325,13 @@ volatile uint32 newBytes = 0;
RESET_STATE reset_state = DTR_UNSET;
uint8 line_dtr_rts = 0;
+/*
+ * Endpoint callbacks
+ */
+
static void (*ep_int_in[7])(void) =
{vcomDataTxCb,
- vcomManagementCb,
+ NOP_Process,
NOP_Process,
NOP_Process,
NOP_Process,
@@ -326,17 +348,154 @@ static void (*ep_int_out[7])(void) =
NOP_Process};
/*
- * VCOM callbacks
+ * Globals required by usb_lib/
+ */
+
+#define NUM_ENDPTS 0x04
+DEVICE Device_Table = {
+ .Total_Endpoint = NUM_ENDPTS,
+ .Total_Configuration = 1
+};
+
+#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */
+DEVICE_PROP Device_Property = {
+ .Init = usbInit,
+ .Reset = usbReset,
+ .Process_Status_IN = NOP_Process,
+ .Process_Status_OUT = NOP_Process,
+ .Class_Data_Setup = usbDataSetup,
+ .Class_NoData_Setup = usbNoDataSetup,
+ .Class_Get_Interface_Setting = usbGetInterfaceSetting,
+ .GetDeviceDescriptor = usbGetDeviceDescriptor,
+ .GetConfigDescriptor = usbGetConfigDescriptor,
+ .GetStringDescriptor = usbGetStringDescriptor,
+ .RxEP_buffer = NULL,
+ .MaxPacketSize = MAX_PACKET_SIZE
+};
+
+USER_STANDARD_REQUESTS User_Standard_Requests = {
+ .User_GetConfiguration = NOP_Process,
+ .User_SetConfiguration = usbSetConfiguration,
+ .User_GetInterface = NOP_Process,
+ .User_SetInterface = NOP_Process,
+ .User_GetStatus = NOP_Process,
+ .User_ClearFeature = NOP_Process,
+ .User_SetEndPointFeature = NOP_Process,
+ .User_SetDeviceFeature = NOP_Process,
+ .User_SetDeviceAddress = usbSetDeviceAddress
+};
+
+/*
+ * CDC ACM interface
+ */
+
+void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) {
+ /* Present ourselves to the host */
+ gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP);
+ gpio_write_bit(disc_dev, disc_bit, 0); // presents us to the host
+
+ /* initialize USB peripheral */
+ usb_init_usblib(ep_int_in, ep_int_out);
+}
+
+void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) {
+ // These are just guesses about how to do this, but it seems to work.
+ // TODO: verify this with USB spec
+ nvic_irq_disable(NVIC_USB_LP_CAN_RX0);
+ gpio_write_bit(disc_dev, disc_bit, 1);
+}
+
+void usb_cdcacm_putc(char ch) {
+ while (!usb_cdcacm_tx((uint8*)&ch, 1))
+ ;
+}
+
+/* This function is non-blocking.
+ *
+ * It copies data from a usercode buffer into the USB peripheral TX
+ * buffer and return the number placed in that buffer.
*/
+uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) {
+ /* Last transmission hasn't finished, abort */
+ if (countTx) {
+ return 0;
+ }
+
+ // We can only put VCOM_TX_EPSIZE bytes in the buffer
+ /* FIXME then why are we only copying half as many? */
+ if (len > VCOM_TX_EPSIZE / 2) {
+ len = VCOM_TX_EPSIZE / 2;
+ }
+
+ // Try to load some bytes if we can
+ if (len) {
+ usb_copy_to_pma(buf, len, VCOM_TX_ADDR);
+ usb_set_ep_tx_count(VCOM_TX_ENDP, len);
+ countTx += len;
+ usb_set_ep_tx_stat(VCOM_TX_ENDP, USB_EP_STAT_TX_VALID);
+ }
-void vcomDataTxCb(void) {
+ return len;
+}
+
+/* returns the number of available bytes are in the recv FIFO */
+uint32 usb_cdcacm_data_available(void) {
+ return newBytes;
+}
+
+uint16 usb_cdcacm_get_pending() {
+ return countTx;
+}
+
+/* Nonblocking byte receive.
+ *
+ * Copies up to len bytes from our private data buffer (*NOT* the PMA)
+ * into buf and deq's the FIFO. */
+uint32 usb_cdcacm_rx(uint8* buf, uint32 len) {
+ static int offset = 0;
+ int i;
+
+ if (len > newBytes) {
+ len = newBytes;
+ }
+
+ for (i = 0; i < len; i++) {
+ buf[i] = vcomBufferRx[i + offset];
+ }
+
+ newBytes -= len;
+ offset += len;
+
+ /* Re-enable the RX endpoint, which we had set to receive 0 bytes */
+ if (newBytes == 0) {
+ usb_set_ep_rx_count(VCOM_RX_ENDP, VCOM_RX_EPSIZE);
+ usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_VALID);
+ offset = 0;
+ }
+
+ return len;
+}
+
+uint8 usb_cdcacm_get_dtr() {
+ return ((line_dtr_rts & CONTROL_LINE_DTR) != 0);
+}
+
+uint8 usb_cdcacm_get_rts() {
+ return ((line_dtr_rts & CONTROL_LINE_RTS) != 0);
+}
+
+/*
+ * Callbacks
+ */
+
+static void vcomDataTxCb(void) {
/* assumes tx transactions are atomic 64 bytes (nearly certain they are) */
countTx = 0;
}
#define EXC_RETURN 0xFFFFFFF9
#define DEFAULT_CPSR 0x61000000
-void vcomDataRxCb(void) {
+static void vcomDataRxCb(void) {
/* FIXME this is mad buggy */
/* setEPRxCount on the previous cycle should garuntee
@@ -393,22 +552,16 @@ void vcomDataRxCb(void) {
usb_copy_from_pma(vcomBufferRx, newBytes, VCOM_RX_ADDR);
}
-void vcomManagementCb(void) {
- /* unused. This enpoint would callback if we had sent a linestate
- changed notification */
-}
-
-u8* vcomGetSetLineCoding(uint16 length) {
+static uint8* vcomGetSetLineCoding(uint16 length) {
if (length == 0) {
pInformation->Ctrl_Info.Usb_wLength = sizeof(USB_Line_Coding);
}
return (uint8*)&line_coding;
}
-void vcomSetLineState(void) {
-}
+static void usbInit(void) {
+ pInformation->Current_Configuration = 0;
-RESULT usbPowerOn(void) {
USB_BASE->CNTR = USB_CNTR_FRES;
USBLIB->irq_mask = 0;
@@ -417,13 +570,6 @@ RESULT usbPowerOn(void) {
USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
USB_BASE->CNTR = USBLIB->irq_mask;
- return USB_SUCCESS;
-}
-
-void usbInit(void) {
- pInformation->Current_Configuration = 0;
- usbPowerOn();
-
USB_BASE->ISTR = 0;
USBLIB->irq_mask = USB_ISR_MSK;
USB_BASE->CNTR = USBLIB->irq_mask;
@@ -434,7 +580,7 @@ void usbInit(void) {
/* choose addresses to give endpoints the max 64 byte buffers */
#define BTABLE_ADDRESS 0x00
-void usbReset(void) {
+static void usbReset(void) {
pInformation->Current_Configuration = 0;
/* current feature is current bmAttributes */
@@ -483,16 +629,7 @@ void usbReset(void) {
countTx = 0;
}
-void usbStatusIn(void) {
- /* adjust the usart line coding
- if we wish to couple the CDC line coding
- with the real usart port */
-}
-
-void usbStatusOut(void) {
-}
-
-RESULT usbDataSetup(uint8 request) {
+static RESULT usbDataSetup(uint8 request) {
uint8 *(*CopyRoutine)(uint16);
CopyRoutine = NULL;
@@ -521,7 +658,7 @@ RESULT usbDataSetup(uint8 request) {
return USB_SUCCESS;
}
-RESULT usbNoDataSetup(u8 request) {
+static RESULT usbNoDataSetup(uint8 request) {
uint8 new_signal;
/* we support set com feature but dont handle it */
@@ -578,7 +715,7 @@ RESULT usbNoDataSetup(u8 request) {
return USB_UNSUPPORT;
}
-RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
+static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
if (alt_setting > 0) {
return USB_UNSUPPORT;
} else if (interface > 1) {
@@ -588,15 +725,15 @@ RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
return USB_SUCCESS;
}
-u8* usbGetDeviceDescriptor(u16 length) {
+static uint8* usbGetDeviceDescriptor(uint16 length) {
return Standard_GetDescriptorData(length, &Device_Descriptor);
}
-u8* usbGetConfigDescriptor(u16 length) {
+static uint8* usbGetConfigDescriptor(uint16 length) {
return Standard_GetDescriptorData(length, &Config_Descriptor);
}
-u8* usbGetStringDescriptor(u16 length) {
+static uint8* usbGetStringDescriptor(uint16 length) {
uint8 wValue0 = pInformation->USBwValue0;
if (wValue0 > 2) {
@@ -605,147 +742,12 @@ u8* usbGetStringDescriptor(u16 length) {
return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]);
}
-/* internal callbacks to respond to standard requests */
-void usbSetConfiguration(void) {
+static void usbSetConfiguration(void) {
if (pInformation->Current_Configuration != 0) {
USBLIB->state = USB_CONFIGURED;
}
}
-void usbSetDeviceAddress(void) {
+static void usbSetDeviceAddress(void) {
USBLIB->state = USB_ADDRESSED;
}
-
-/*
- * Globals required by usb_lib/
- */
-
-#define NUM_ENDPTS 0x04
-DEVICE Device_Table =
- {NUM_ENDPTS,
- 1};
-
-#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */
-DEVICE_PROP Device_Property =
- {usbInit,
- usbReset,
- usbStatusIn,
- usbStatusOut,
- usbDataSetup,
- usbNoDataSetup,
- usbGetInterfaceSetting,
- usbGetDeviceDescriptor,
- usbGetConfigDescriptor,
- usbGetStringDescriptor,
- 0,
- MAX_PACKET_SIZE};
-
-USER_STANDARD_REQUESTS User_Standard_Requests =
- {NOP_Process,
- usbSetConfiguration,
- NOP_Process,
- NOP_Process,
- NOP_Process,
- NOP_Process,
- NOP_Process,
- NOP_Process,
- usbSetDeviceAddress};
-
-/*
- * CDC ACM routines
- */
-
-void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) {
- /* Present ourselves to the host */
- gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP);
- gpio_write_bit(disc_dev, disc_bit, 0); // presents us to the host
-
- /* initialize USB peripheral */
- usb_init_usblib(ep_int_in, ep_int_out);
-}
-
-void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) {
- // These are just guesses about how to do this, but it seems to work.
- // TODO: verify this with USB spec
- nvic_irq_disable(NVIC_USB_LP_CAN_RX0);
- gpio_write_bit(disc_dev, disc_bit, 1);
-}
-
-void usb_cdcacm_putc(char ch) {
- while (!usb_cdcacm_tx((uint8*)&ch, 1))
- ;
-}
-
-/* This function is non-blocking.
- *
- * It copies data from a usercode buffer into the USB peripheral TX
- * buffer and return the number placed in that buffer.
- */
-uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) {
- /* Last transmission hasn't finished, abort */
- if (countTx) {
- return 0;
- }
-
- // We can only put VCOM_TX_EPSIZE bytes in the buffer
- /* FIXME then why are we only copying half as many? */
- if (len > VCOM_TX_EPSIZE / 2) {
- len = VCOM_TX_EPSIZE / 2;
- }
-
- // Try to load some bytes if we can
- if (len) {
- usb_copy_to_pma(buf, len, VCOM_TX_ADDR);
- usb_set_ep_tx_count(VCOM_TX_ENDP, len);
- countTx += len;
- usb_set_ep_tx_stat(VCOM_TX_ENDP, USB_EP_STAT_TX_VALID);
- }
-
- return len;
-}
-
-/* returns the number of available bytes are in the recv FIFO */
-uint32 usb_cdcacm_data_available(void) {
- return newBytes;
-}
-
-uint16 usb_cdcacm_get_pending() {
- return countTx;
-}
-
-/* Nonblocking byte receive.
- *
- * Copies up to len bytes from our private data buffer (*NOT* the PMA)
- * into buf and deq's the FIFO. */
-uint32 usb_cdcacm_rx(uint8* buf, uint32 len) {
- static int offset = 0;
- int i;
-
- if (len > newBytes) {
- len = newBytes;
- }
-
- for (i = 0; i < len; i++) {
- buf[i] = vcomBufferRx[i + offset];
- }
-
- newBytes -= len;
- offset += len;
-
- /* Re-enable the RX endpoint, which we had set to receive 0 bytes */
- if (newBytes == 0) {
- usb_set_ep_rx_count(VCOM_RX_ENDP, VCOM_RX_EPSIZE);
- usb_set_ep_rx_stat(VCOM_RX_ENDP, USB_EP_STAT_RX_VALID);
- offset = 0;
- }
-
- return len;
-}
-
-uint8 usb_cdcacm_get_dtr() {
- return ((line_dtr_rts & CONTROL_LINE_DTR) != 0);
-}
-
-uint8 usb_cdcacm_get_rts() {
- return ((line_dtr_rts & CONTROL_LINE_RTS) != 0);
-}