Commit 24524330 authored by Léo Grange's avatar Léo Grange

dirty implementation of TTY input for CDC/ACM USB device

parent 82096b6c
......@@ -33,6 +33,9 @@ static struct cyclic_fifo _usb_fifo_ep1o = {
// setup callback
usb_setup_callback_t _usb_setup_callback = NULL;
// ep1 receive callback
usb_receive_callback_t _usb_ep1_receive_callback = NULL;
// debug stuff
extern int _magic_lock;
......@@ -172,6 +175,12 @@ int usb_receive(int endpoint, char *data, size_t size, int flags) {
}
void usb_set_receive_callback(int endpoint, usb_receive_callback_t callback) {
if(endpoint == USB_EP_EP1)
_usb_ep1_receive_callback = callback;
}
static void usb_sh3_ep1_read(int nbread) {
(void)nbread; // not used for now
......@@ -354,24 +363,32 @@ void usb_sh3_interrupt_handler() {
int i;
int nbreceived = USB.EPSZ1;
// try to copy received data to ep1 buffer
if(_usb_fifo_ep1o.size + nbreceived <= _usb_fifo_ep1o.max_size) {
// copy in cyclic FIFO need some additionnal things :
int bufpos = (_usb_fifo_ep1o.top + _usb_fifo_ep1o.size) % _usb_fifo_ep1o.max_size;
for(i=0; i<nbreceived; i++, bufpos = bufpos >= _usb_fifo_ep1o.max_size - 1 ? 0 : bufpos+1 ) {
_usb_fifo_ep1o.buffer[bufpos] = USB.EPDR1;
}
_usb_fifo_ep1o.size += nbreceived;
// call the async receive callback?
if(_usb_ep1_receive_callback != NULL) {
for(i=0; i<nbreceived; i++)
_usb_ep1_receive_callback(USB.EPDR1);
USB.TRG.BIT.EP1RDFN = 1;
}
else {
//printk(LOG_DEBUG, "usb: no enougth space for ep1o\n");
// in addition, EP1FULL interrupt is disabled
// the function usb_sh3_ep1_read() is used to signal some part of
// the buffer was read, and maybe EP1FULL can be re-enabled
USB.IER0.BIT.EP1FULL = 0;
// try to copy received data to ep1 buffer
if(_usb_fifo_ep1o.size + nbreceived <= _usb_fifo_ep1o.max_size) {
// copy in cyclic FIFO need some additionnal things :
int bufpos = (_usb_fifo_ep1o.top + _usb_fifo_ep1o.size) % _usb_fifo_ep1o.max_size;
for(i=0; i<nbreceived; i++, bufpos = bufpos >= _usb_fifo_ep1o.max_size - 1 ? 0 : bufpos+1 ) {
_usb_fifo_ep1o.buffer[bufpos] = USB.EPDR1;
}
_usb_fifo_ep1o.size += nbreceived;
USB.TRG.BIT.EP1RDFN = 1;
}
else {
//printk(LOG_DEBUG, "usb: no enougth space for ep1o\n");
// in addition, EP1FULL interrupt is disabled
// the function usb_sh3_ep1_read() is used to signal some part of
// the buffer was read, and maybe EP1FULL can be re-enabled
USB.IER0.BIT.EP1FULL = 0;
}
}
USB.IFR0.BIT.EP1FULL = 0;
......
......@@ -28,11 +28,14 @@ static int acm_tty_is_ready(struct tty *tty);
static int acm_tty_write(struct tty *tty, const char *data, size_t len);
static int acm_tty_putchar(struct tty *tty, char c);
static const struct tty_ops _acm_tty_ops = {
.ioctl_setwinsize = NULL,
.ioctl_getwinsize = NULL,
.is_ready = &acm_tty_is_ready,
.tty_write = &acm_tty_write
.tty_write = &acm_tty_write,
.putchar = &acm_tty_putchar
};
static struct tty _acm_tty = {
......@@ -43,9 +46,17 @@ static struct tty _acm_tty = {
};
// callback used to do TTY job for each input character
static int acm_input_char(char c) {
tty_input_char(&_acm_tty, c);
return 0;
}
void acm_usb_init() {
tty_default_init(&_acm_tty);
cdc_acm_init();
cdc_acm_set_receive_callback(&acm_input_char);
}
......@@ -85,7 +96,8 @@ ssize_t acm_usb_write(struct file *filep, void *source, size_t len) {
ssize_t acm_usb_read(struct file *filep, void *dest, size_t len) {
if(cdc_acm_is_ready()) {
return cdc_acm_receive(dest, len);
return tty_read(&_acm_tty, dest, len);
//return cdc_acm_receive(dest, len);
}
return -EIO;
......@@ -119,3 +131,9 @@ static int acm_tty_write(struct tty *tty, const char *data, size_t len) {
}
return -EIO;
}
static int acm_tty_putchar(struct tty *tty, char c) {
acm_tty_write(tty, &c, 1);
return 0;
}
......@@ -157,9 +157,6 @@ static struct usb_endpoint_ability _cdc_enpoints[3] = {
};
void cdc_acm_init() {
// get a configuration for needed endpoints
if(usb_find_endpoint_config(3, _cdc_enpoints) == 0) {
......@@ -366,3 +363,8 @@ size_t cdc_acm_receive(char *dest, size_t size) {
return 0;
}
// use the USB-level callback
void cdc_acm_set_receive_callback(usb_receive_callback_t callback) {
usb_set_receive_callback(_epdesc1.b_endpoint_addr & 0x0F, callback);
}
......@@ -11,7 +11,8 @@
#include <utils/types.h>
struct usb_setup;
//struct usb_setup;
#include <device/usb/usb_device_protocol.h>
/**
......@@ -44,4 +45,10 @@ size_t cdc_acm_receive(char *dest, size_t size);
int cdc_acm_setup_handler(const struct usb_setup *setup);
/**
* Set the low-level input character handler (called for each received byte).
*/
void cdc_acm_set_receive_callback(usb_receive_callback_t callback);
#endif //_DEVICE_USB_CDC_ACM
......@@ -237,10 +237,21 @@ int usb_send(int endpoint, const char *data, size_t size);
*
* Returns the number of bytes effectively received, or negative value
* if any error occurs or if endpoint can't receive any data.
* TODO should be marked obsolete (synchronous receive!)
*/
int usb_receive(int endpoint, char *data, size_t size, int flags);
typedef int (*usb_receive_callback_t)(char c);
/**
* Callback used for each byte received asynchronously (a NULL callback
* will do nothing).
* Only some endpoints may support that.
*/
void usb_set_receive_callback(int endpoint, usb_receive_callback_t callback);
/**
* Structure used to describe endpoints at kernel level.
*/
......
......@@ -4,7 +4,7 @@
static const struct termios _tty_default_termios = {
.c_cc = {
ASCII_CTRL('D'), // VEOF
'\n', // VEOL
'\0', // VEOL (\n and \r already handled)
'\b', // VERASE
ASCII_CTRL('C'), // VINTR
ASCII_CTRL('U'), // VKILL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment