From bfabdf3ed83f75bd36be16e23dda54b5d1e38520 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 29 Nov 2010 23:08:04 +0100 Subject: digital/dev2: add TWI master module --- digital/dev2/src/common/usb_twi.c | 279 +++++++++++++++++++++++++++++++++ digital/dev2/src/common/usb_twi.h | 37 +++++ digital/dev2/src/usb_twi/Makefile | 14 ++ digital/dev2/src/usb_twi/avrconfig.h | 63 ++++++++ digital/dev2/src/usb_twi/descriptors.c | 166 ++++++++++++++++++++ digital/dev2/src/usb_twi/descriptors.h | 36 +++++ digital/dev2/src/usb_twi/main.c | 130 +++++++++++++++ 7 files changed, 725 insertions(+) create mode 100644 digital/dev2/src/common/usb_twi.c create mode 100644 digital/dev2/src/common/usb_twi.h create mode 100644 digital/dev2/src/usb_twi/Makefile create mode 100644 digital/dev2/src/usb_twi/avrconfig.h create mode 100644 digital/dev2/src/usb_twi/descriptors.c create mode 100644 digital/dev2/src/usb_twi/descriptors.h create mode 100644 digital/dev2/src/usb_twi/main.c (limited to 'digital/dev2/src') diff --git a/digital/dev2/src/common/usb_twi.c b/digital/dev2/src/common/usb_twi.c new file mode 100644 index 00000000..e83a94d9 --- /dev/null +++ b/digital/dev2/src/common/usb_twi.c @@ -0,0 +1,279 @@ +/* usb_twi.c */ +/* dev2 - Multi-purpose development board using USB and Ethernet. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ +#include "common.h" + +#include "usb_twi.h" +#include "descriptors.h" + +#include "modules/twi/twi.h" +#include "modules/usb/usb.h" + +/** Parser steps. */ +enum +{ + /** Nothing received yet. */ + PARSER_WAIT_COMMAND, + /** Command received, wait address most significant quartet. */ + PARSER_WAIT_ADDRESS_MSQ, + /** First address quartet received, wait second one. */ + PARSER_WAIT_ADDRESS_LSQ, + /** Wait data or end of line. */ + PARSER_WAIT_DATA_OR_EOL, + /** Wait data second quartet. */ + PARSER_WAIT_DATA_LSQ, +}; + +/** Context. */ +struct usb_twi_t +{ + /** Buffer used for transmission or reception. */ + uint8_t buffer[TWI_BUFFER_SIZE]; + /** Number of bytes in buffer. */ + uint8_t buffer_tail; + /** Number of bytes sent back to USB. */ + uint8_t buffer_head; + /** Command to execute. */ + char command; + /** Slave address. */ + uint8_t slave; + /** Parser step. */ + uint8_t parser_step; + /** Parser first quartet. */ + uint8_t parser_msq; + /** Output buffer (in case of USB not ready). */ + char output_buffer[4]; + /** Position in output buffer of next character to send. */ + uint8_t output_buffer_head; +}; + +/** Global context. */ +struct usb_twi_t usb_twi_global; +#define ctx usb_twi_global + +void +usb_twi_init (void) +{ + twi_init (0xfe); +} + +void +usb_twi_uninit (void) +{ + twi_uninit (); +} + +/** Return non zero if there is characters to send. */ +static uint8_t +usb_twi_poll (void) +{ + return ctx.output_buffer[ctx.output_buffer_head]; +} + +/** Output byte to output buffer. */ +static void +usb_twi_ouput_byte (uint8_t p, uint8_t b) +{ + uint8_t i; + char c; + for (i = 0; i < 2; i++) + { + c = "0123456789abcdef"[b >> 4]; + ctx.output_buffer[p++] = c; + b <<= 4; + } +} + +/** Return a character from the output buffer and reload it from buffer if + * needed. */ +static char +usb_twi_getc (void) +{ + char c; + uint8_t p; + /* Take a character in output buffer. */ + c = ctx.output_buffer[ctx.output_buffer_head]; + ctx.output_buffer_head++; + /* Reload from buffer if needed. */ + if (!ctx.output_buffer[ctx.output_buffer_head] + && ctx.buffer_head != ctx.buffer_tail) + { + ctx.output_buffer_head = 0; + p = 0; + usb_twi_ouput_byte (p, ctx.buffer[ctx.buffer_head++]); + p += 2; + if (ctx.buffer_head == ctx.buffer_tail) + ctx.output_buffer[p++] = '\r'; + ctx.output_buffer[p] = '\0'; + } + return c; +} + +static uint8_t +usb_twi_get_hex (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else + return 0xff; +} + +static uint8_t +usb_twi_exec (void) +{ + uint8_t r, p, l; + if (ctx.command == 's') + { + twi_master_send (ctx.slave, ctx.buffer, ctx.buffer_tail); + r = twi_master_wait (); + ctx.buffer[0] = r; + ctx.buffer_head = 0; + ctx.buffer_tail = 1; + ctx.output_buffer_head = 0; + p = 0; + ctx.output_buffer[p++] = 'S'; + ctx.output_buffer[p++] = '\0'; + return 1; + } + else if (ctx.command == 'r' && ctx.buffer_tail == 1) + { + l = ctx.buffer[0]; + twi_master_recv (ctx.slave, ctx.buffer, l); + r = twi_master_wait (); + ctx.buffer_head = 0; + ctx.buffer_tail = r; + ctx.output_buffer_head = 0; + p = 0; + ctx.output_buffer[p++] = 'R'; + if (r == 0) + ctx.output_buffer[p++] = '\r'; + ctx.output_buffer[p++] = '\0'; + return 1; + } + else + return 0; +} + +static void +usb_twi_accept (char c) +{ + uint8_t q; + /* Purge output buffer. */ + ctx.output_buffer_head = 0; + ctx.output_buffer[0] = '\0'; + /* Accept FSM. */ + switch (ctx.parser_step) + { + case PARSER_WAIT_COMMAND: + if (c == 's' || c == 'r') + { + ctx.command = c; + ctx.buffer_tail = 0; + ctx.parser_step++; + return; + } + break; + case PARSER_WAIT_ADDRESS_MSQ: + q = usb_twi_get_hex (c); + if (q != 0xff) + { + ctx.parser_msq = q; + ctx.parser_step++; + return; + } + break; + case PARSER_WAIT_ADDRESS_LSQ: + q = usb_twi_get_hex (c); + if (q != 0xff) + { + ctx.slave = ctx.parser_msq << 4 | q; + ctx.parser_step++; + return; + } + break; + case PARSER_WAIT_DATA_OR_EOL: + if (c == '\r') + { + ctx.parser_step = PARSER_WAIT_COMMAND; + if (usb_twi_exec ()) + return; + } + else if (ctx.buffer_tail < TWI_BUFFER_SIZE) + { + q = usb_twi_get_hex (c); + if (q != 0xff) + { + ctx.parser_msq = q; + ctx.parser_step++; + return; + } + } + break; + case PARSER_WAIT_DATA_LSQ: + q = usb_twi_get_hex (c); + if (q != 0xff) + { + ctx.buffer[ctx.buffer_tail++] = ctx.parser_msq << 4 | q; + ctx.parser_step--; + return; + } + break; + } + /* If here, there was an error. */ + ctx.buffer_tail = ctx.buffer_head = 0; + ctx.output_buffer_head = 0; + ctx.output_buffer[0] = '!'; + ctx.output_buffer[1] = '\r'; + ctx.output_buffer[2] = '\0'; + ctx.parser_step = PARSER_WAIT_COMMAND; +} + +void +usb_twi_task (void) +{ + Endpoint_SelectEndpoint (TWI_RX_EPNUM); + /* If data is available from USB: */ + if (Endpoint_ReadWriteAllowed ()) + { + /* Read as much as possible, and clear endpoint. */ + do { + usb_twi_accept (Endpoint_Read_Byte ()); + } while (Endpoint_ReadWriteAllowed ()); + Endpoint_ClearCurrentBank (); + } + /* If data is available from uart and there is room in the TX endpoint: */ + Endpoint_SelectEndpoint (TWI_TX_EPNUM); + if (usb_twi_poll () && Endpoint_ReadWriteAllowed ()) + { + do { + Endpoint_Write_Byte (usb_twi_getc ()); + } while (usb_twi_poll () && Endpoint_ReadWriteAllowed ()); + Endpoint_ClearCurrentBank (); + } +} + diff --git a/digital/dev2/src/common/usb_twi.h b/digital/dev2/src/common/usb_twi.h new file mode 100644 index 00000000..ccc227bc --- /dev/null +++ b/digital/dev2/src/common/usb_twi.h @@ -0,0 +1,37 @@ +#ifndef usb_twi_h +#define usb_twi_h +/* usb_twi.h */ +/* dev2 - Multi-purpose development board using USB and Ethernet. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +void +usb_twi_init (void); + +void +usb_twi_uninit (void); + +void +usb_twi_task (void); + +#endif /* usb_twi_h */ diff --git a/digital/dev2/src/usb_twi/Makefile b/digital/dev2/src/usb_twi/Makefile new file mode 100644 index 00000000..48a85cfc --- /dev/null +++ b/digital/dev2/src/usb_twi/Makefile @@ -0,0 +1,14 @@ +BASE = ../../../avr +AVR_PROGS = dev2_twi +dev2_twi_SOURCES = main.c descriptors.c select.c usb_twi.c +MODULES = usb twi +CONFIGFILE = avrconfig.h +AVR_MCU = at90usb162 +# -O2 : speed +# -Os : size +OPTIMIZE = -Os + +INCLUDES = -I.. -I. +vpath %.c ../common + +include $(BASE)/make/Makefile.gen diff --git a/digital/dev2/src/usb_twi/avrconfig.h b/digital/dev2/src/usb_twi/avrconfig.h new file mode 100644 index 00000000..5c2d92ce --- /dev/null +++ b/digital/dev2/src/usb_twi/avrconfig.h @@ -0,0 +1,63 @@ +#ifndef avrconfig_h +#define avrconfig_h +/* avrconfig.h */ +/* dev2 - Multi-purpose development board using USB and Ethernet. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +/* utils */ +/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800, + * 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */ +#define AC_FREQ 8000000 + +/* twi - TWI module. */ +/** Driver to implement TWI: HARD, SOFT, or USI. */ +#define AC_TWI_DRIVER SOFT +/** Do not use interrupts. */ +#define AC_TWI_NO_INTERRUPT 0 +/** TWI frequency, should really be 100 kHz. */ +#define AC_TWI_FREQ 10000 +/** Enable slave part. */ +#define AC_TWI_SLAVE_ENABLE 0 +/** Enable master part. */ +#define AC_TWI_MASTER_ENABLE 1 +/** Use polled slave mode: received data is stored in a buffer which can be + * polled using twi_slave_poll. */ +#define AC_TWI_SLAVE_POLLED 1 +/** Slave reception callback to be defined by the user when not in polled + * mode. */ +#undef AC_TWI_SLAVE_RECV +/** Master transfer completion callback, optionally defined by the user, called + * at end of master transfer. */ +#undef AC_TWI_MASTER_DONE +/** Use internal pull up. */ +#define AC_TWI_PULL_UP 1 +/** SDA line IO for SOFT driver. */ +#define AC_TWI_SOFT_SDA_IO D, 7 +/** SCL line IO for SOFT driver. */ +#define AC_TWI_SOFT_SCL_IO D, 5 + +/* usb */ +#include "modules/usb/lufaconfig.h" + +#endif /* avrconfig_h */ diff --git a/digital/dev2/src/usb_twi/descriptors.c b/digital/dev2/src/usb_twi/descriptors.c new file mode 100644 index 00000000..728184f6 --- /dev/null +++ b/digital/dev2/src/usb_twi/descriptors.c @@ -0,0 +1,166 @@ +/* descriptors.c */ +/* dev2 - Multi-purpose development board using USB and Ethernet. {{{ + * + * Copyright (C) 2009 Nicolas Schodet + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ +#include "common.h" + +#include "modules/usb/usb.h" + +#include + +#include "descriptors.h" + +/* Configuration structure. */ +typedef struct +{ + USB_Descriptor_Configuration_Header_t Config; + USB_Descriptor_Interface_t TS1_Interface; + USB_Descriptor_Endpoint_t TS1_DataOutEndpoint; + USB_Descriptor_Endpoint_t TS1_DataInEndpoint; +} USB_Descriptor_Configuration_t; + +USB_Descriptor_Device_t PROGMEM DeviceDescriptor = +{ + Header: { Size: sizeof (USB_Descriptor_Device_t), Type: DTYPE_Device }, + USBSpecification: VERSION_BCD (01.10), + Class: 0xFF, + SubClass: 0x00, + Protocol: 0x00, + Endpoint0Size: 8, + /* Taken from LUFA IDs. */ + VendorID: 0x03EB, + ProductID: 0x204E, + ReleaseNumber: 0x0000, + ManufacturerStrIndex: 0x01, + ProductStrIndex: 0x02, + SerialNumStrIndex: NO_DESCRIPTOR, + NumberOfConfigurations: 1 +}; + +USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = +{ + Config: + { + Header: { Size: sizeof (USB_Descriptor_Configuration_Header_t), + Type: DTYPE_Configuration }, + TotalConfigurationSize: sizeof (USB_Descriptor_Configuration_t), + TotalInterfaces: 1, + ConfigurationNumber: 1, + ConfigurationStrIndex: NO_DESCRIPTOR, + ConfigAttributes: (USB_CONFIG_ATTR_BUSPOWERED | + USB_CONFIG_ATTR_SELFPOWERED), + MaxPowerConsumption: USB_CONFIG_POWER_MA (100) + }, + + TS1_Interface: + { + Header: { Size: sizeof (USB_Descriptor_Interface_t), + Type: DTYPE_Interface }, + InterfaceNumber: 0, + AlternateSetting: 0, + TotalEndpoints: 2, + Class: 0xFF, + SubClass: 0x00, + Protocol: 0x00, + InterfaceStrIndex: NO_DESCRIPTOR + }, + + TS1_DataOutEndpoint: + { + Header: { Size: sizeof (USB_Descriptor_Endpoint_t), + Type: DTYPE_Endpoint }, + EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_OUT | TWI_RX_EPNUM), + Attributes: EP_TYPE_BULK, + EndpointSize: TWI_RX_EPSIZE, + PollingIntervalMS: 0x00 + }, + + TS1_DataInEndpoint: + { + Header: { Size: sizeof (USB_Descriptor_Endpoint_t), + Type: DTYPE_Endpoint }, + EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_IN | TWI_TX_EPNUM), + Attributes: EP_TYPE_BULK, + EndpointSize: TWI_TX_EPSIZE, + PollingIntervalMS: 0x00 + }, +}; + +USB_Descriptor_String_t PROGMEM LanguageString = +{ + Header: { Size: USB_STRING_LEN (1), Type: DTYPE_String }, + UnicodeString: {LANGUAGE_ID_ENG} +}; + +USB_Descriptor_String_t PROGMEM ManufacturerString = +{ + Header: { Size: USB_STRING_LEN (7), Type: DTYPE_String }, + UnicodeString: L"APBTeam" +}; + +USB_Descriptor_String_t PROGMEM ProductString = +{ + Header: { Size: USB_STRING_LEN (8), Type: DTYPE_String }, + UnicodeString: L"dev2 twi" +}; + +uint16_t +USB_GetDescriptor (const uint16_t wValue, const uint8_t wIndex, + void ** const DescriptorAddress) +{ + const uint8_t DescriptorType = wValue >> 8; + const uint8_t DescriptorNumber = wValue & 0xFF; + void * Address = NULL; + uint16_t Size = NO_DESCRIPTOR; + switch (DescriptorType) + { + case DTYPE_Device: + Address = DESCRIPTOR_ADDRESS (DeviceDescriptor); + Size = sizeof (USB_Descriptor_Device_t); + break; + case DTYPE_Configuration: + Address = DESCRIPTOR_ADDRESS (ConfigurationDescriptor); + Size = sizeof (USB_Descriptor_Configuration_t); + break; + case DTYPE_String: + switch (DescriptorNumber) + { + case 0x00: + Address = DESCRIPTOR_ADDRESS (LanguageString); + Size = pgm_read_byte (&LanguageString.Header.Size); + break; + case 0x01: + Address = DESCRIPTOR_ADDRESS (ManufacturerString); + Size = pgm_read_byte (&ManufacturerString.Header.Size); + break; + case 0x02: + Address = DESCRIPTOR_ADDRESS (ProductString); + Size = pgm_read_byte (&ProductString.Header.Size); + break; + } + break; + } + *DescriptorAddress = Address; + return Size; +} + diff --git a/digital/dev2/src/usb_twi/descriptors.h b/digital/dev2/src/usb_twi/descriptors.h new file mode 100644 index 00000000..e63cafc4 --- /dev/null +++ b/digital/dev2/src/usb_twi/descriptors.h @@ -0,0 +1,36 @@ +#ifndef descriptors_h +#define descriptors_h +/* descriptors.h */ +/* dev2 - Multi-purpose development board using USB and Ethernet. {{{ + * + * Copyright (C) 2009 Nicolas Schodet + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +/* Endpoints. */ +#define TWI_TX_EPNUM 1 +#define TWI_TX_EPSIZE 16 +#define TWI_RX_EPNUM 2 +#define TWI_RX_EPSIZE 16 + +#define TWI_BUFFER_SIZE 128 + +#endif /* descriptors_h */ diff --git a/digital/dev2/src/usb_twi/main.c b/digital/dev2/src/usb_twi/main.c new file mode 100644 index 00000000..fa1f2b98 --- /dev/null +++ b/digital/dev2/src/usb_twi/main.c @@ -0,0 +1,130 @@ +/* main.c */ +/* dev2 - Multi-purpose development board using USB and Ethernet. {{{ + * + * Copyright (C) 2009 Nicolas Schodet + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ +#include "common.h" + +#include "modules/usb/usb.h" +#include "io.h" + +#include + +#include "descriptors.h" +#include "common/usb_twi.h" +#include "common/select.h" + +HANDLES_EVENT (USB_Connect); +HANDLES_EVENT (USB_Disconnect); +HANDLES_EVENT (USB_ConfigurationChanged); +HANDLES_EVENT (USB_UnhandledControlPacket); + +volatile uint8_t usb_connected, usb_configured; + +int +main (void) +{ + /* Disable watchdog if enabled by bootloader/fuses. */ + MCUSR &= ~(1 << WDRF); + wdt_disable (); + /* Disable Clock Division. */ + SetSystemClockPrescaler (0); + /* Initialise hardware. */ + select_init (); + /* Initialize USB Subsystem. */ + USB_Init (); + /* Main loop. */ + while (1) + { + if (usb_connected) + USB_USBTask (); + if (usb_configured) + { + usb_twi_task (); + } + } +} + +EVENT_HANDLER (USB_Connect) +{ + usb_connected = 1; +} + +EVENT_HANDLER (USB_Disconnect) +{ + usb_connected = 0; + usb_configured = 0; +} + +EVENT_HANDLER (USB_ConfigurationChanged) +{ + /* Setup Rx and Tx Endpoints for the first port. */ + Endpoint_ConfigureEndpoint (TWI_TX_EPNUM, EP_TYPE_BULK, + ENDPOINT_DIR_IN, TWI_TX_EPSIZE, + ENDPOINT_BANK_SINGLE); + Endpoint_ConfigureEndpoint (TWI_RX_EPNUM, EP_TYPE_BULK, + ENDPOINT_DIR_OUT, TWI_RX_EPSIZE, + ENDPOINT_BANK_SINGLE); + /* Start tasks. */ + usb_configured = 1; +} + +EVENT_HANDLER (USB_UnhandledControlPacket) +{ + /* Process TS specific control requests. */ + switch (bRequest) + { + /* Switch back to DFU mode. */ + case 0: + if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | + REQREC_DEVICE)) + { + Endpoint_ClearSetupReceived (); + /* Send acknowledgement and wait for it to be sent. */ + Endpoint_ClearSetupIN (); + while (!Endpoint_IsSetupINReady ()) + ; + USB_ShutDown (); + /* Jump to bootloader. */ + ((void (*) (void)) 0x3000) (); + } + break; + /* Select output. */ + case 1: + if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | + REQREC_DEVICE)) + { + /* Selector parameter. */ + uint8_t output = Endpoint_Read_Byte (); + Endpoint_ClearSetupReceived (); + /* Select output. */ + usb_twi_uninit (); + select_out (output); + if (select_active (output)) + usb_twi_init (); + /* Send acknowledgement. */ + Endpoint_ClearSetupIN (); + } + break; + } +} + -- cgit v1.2.3