diff --git a/HIDReports.cpp b/HIDReports.cpp index f1535b9..49fad6c 100755 --- a/HIDReports.cpp +++ b/HIDReports.cpp @@ -9,6 +9,8 @@ REPORT(KeyboardMouseJoystick, HID_MOUSE_REPORT_DESCRIPTOR(), HID_KEYBOARD_REPORT REPORT(KeyboardMouse, HID_MOUSE_REPORT_DESCRIPTOR(), HID_KEYBOARD_REPORT_DESCRIPTOR()); REPORT(Keyboard, HID_KEYBOARD_REPORT_DESCRIPTOR()); REPORT(Mouse, HID_MOUSE_REPORT_DESCRIPTOR()); +REPORT(AbsMouse, HID_ABS_MOUSE_REPORT_DESCRIPTOR()); REPORT(KeyboardJoystick, HID_KEYBOARD_REPORT_DESCRIPTOR(), HID_JOYSTICK_REPORT_DESCRIPTOR()); REPORT(Joystick, HID_JOYSTICK_REPORT_DESCRIPTOR()); REPORT(BootKeyboard, HID_BOOT_KEYBOARD_REPORT_DESCRIPTOR()); +REPORT(Consumer, HID_CONSUMER_REPORT_DESCRIPTOR()); diff --git a/MinSysex.c b/MinSysex.c index 68b97a0..f496f27 100644 --- a/MinSysex.c +++ b/MinSysex.c @@ -39,7 +39,6 @@ #define STANDARD_ID_RESPONSE_LENGTH 7 #include "usb_midi_device.h" -#include #include #include //#include @@ -129,12 +128,6 @@ volatile int sysexFinger=0; #define EXC_RETURN 0xFFFFFFF9 #define DEFAULT_CPSR 0x61000000 #define RESET_DELAY 100000 -#if 0 -static void wait_reset(void) { - delay_us(RESET_DELAY); - nvic_sys_reset(); -} -#endif /* -----------------------------------------------------------------------------dealWithItQuickly() * Note: at this point we have established that the sysex belongs to us. @@ -154,36 +147,6 @@ void dealWithItQuickly(){ } case USYSEX_REAL_TIME: break; -#if 0 - case LEAFLABS_MMA_VENDOR_1: - if (sysexBuffer[5]==LGL_RESET_CMD) { - uintptr_t target = (uintptr_t)wait_reset | 0x1; - asm volatile("mov r0, %[stack_top] \n\t" // Reset stack - "mov sp, r0 \n\t" - "mov r0, #1 \n\t" - "mov r1, %[target_addr] \n\t" - "mov r2, %[cpsr] \n\t" - "push {r2} \n\t" // Fake xPSR - "push {r1} \n\t" // PC target addr - "push {r0} \n\t" // Fake LR - "push {r0} \n\t" // Fake R12 - "push {r0} \n\t" // Fake R3 - "push {r0} \n\t" // Fake R2 - "push {r0} \n\t" // Fake R1 - "push {r0} \n\t" // Fake R0 - "mov lr, %[exc_return] \n\t" - "bx lr" - : - : [stack_top] "r" (STACK_TOP), - [target_addr] "r" (target), - [exc_return] "r" (EXC_RETURN), - [cpsr] "r" (DEFAULT_CPSR) - : "r0", "r1", "r2"); - /* Can't happen. */ - ASSERT_FAULT(0); - - } -#endif default: break; } diff --git a/README.md b/README.md index 0ec702f..e906e1f 100644 --- a/README.md +++ b/README.md @@ -108,14 +108,14 @@ to inject keyboard data, you should do: USBHID HID; // create instance of USBHID plugin HIDKeyboard Keyboard(HID); // create a profile -HID.begin(HID_KEYBOARD); +HID.begin(); ``` and then call `Keyboard.print("TextToInject")` to inject keyboard data. Some plugin configurations may require further initialization code or further code that needs to be called inside the Arduino `loop()` function. -See the `BootKeyboard`, `midiout` and `x360` example code for this procedure. +See the `BootKeyboard`, `midiout` and `x360` example code for variants on this procedure. (Additionally, the `USBHID` plugin has a convenience `begin()` method that lets you include an instance of a `USBCompositeSerial` plugin class, and that creates a composite HID-Serial device.) @@ -123,6 +123,22 @@ instance of a `USBCompositeSerial` plugin class, and that creates a composite HI However, if you want a USB device using more than one plugin, then you will NOT call the plugin's `begin()` method. +Note that a single HID plugin can support a device with multiple report profiles including a keyboard, several joysticks, +a mouse, etc.: +``` +USBHID HID; // create instance of USBHID plugin +HIDKeyboard Keyboard(HID); // create a profile +HIDJoystick Joystick1(HID); // create a profile +HIDJoystick Joystick2(HID); // create a profile +HIDMouse Mouse(HID); // create a profile + +HID.begin(); +``` + +Each of the profiles (e.g., Joystick1) contributes a part of the HID report descriptor to USBHID which automatically stitches +them together and assigns report IDs. However, you can also make a single overarching custom HID report descriptor and include +it in the HID.begin() call. The `softjoystick` example does this. + ## Memory limitations There are 320 bytes of hardware buffer memory available after endpoint 0 is taken into account. The following @@ -157,15 +173,21 @@ MIDI.setTXPacketSize(size); ``` The maximum and default packet size is 64. Smaller packet sizes have not been thoroughly tested and may slow things down. In particular, for HID you should make sure your packet size is sufficient for your largest HID report. The CompositeSerial -device also has a control channel whose 16 byte packet size is not adjustable. +device also has a control channel whose 16 byte packet size is not adjustable. Note that for reasons that I do not currently +understand, CompositeSerial RX packets must be a power of two in size. -Note that in the above, RX and TX are from the point of view of the MCU, not the host (i.e., RX corresponds to USB Out and TX +Note also that in the above, RX and TX are from the point of view of the MCU, not the host (i.e., RX corresponds to USB Out and TX to USB In). ## Endpoint limitations -There is one bidirectional endpoint 0 that all endpoints share, and the hardware allows for seven more in each direction. -Each plugin contributes the following count towards the maximum of seven: +There is one bidirectional endpoint 0 that all endpoints share, and the hardware allows for seven more in each direction, +but there are some complications in that the same endpoint number when used in different directions must have some +of the same parameters. The USBComposite library takes care of these complications when allocating endpoints, but if you +have too many plugins, you USBComposite.begin() will return `false` to indicate that you've used up too many. + +This is pretty complicated, but a rule of thumb for having enough endpoints is to make sure that when you add up the +following contributions for the plugins you use, your total is at most seven. * USB Serial: 2 (= 2 TX, 1 RX) @@ -177,10 +199,6 @@ Each plugin contributes the following count towards the maximum of seven: * XBox360 Controller: 1 per controller (= 1 TX, 1 RX) -* XBox360 Wireless Controller: 1 per controller (= 1 TX, 1 RX) - * USB Audio: 1 (= 1 TX or 1 RX depending on mode) * USB Multi Serial: 2 per port (= 2 TX, 1 RX) - -When combining plugins, make sure the contribution does not exceed 7. diff --git a/USBComposite.cpp b/USBComposite.cpp index da719f0..574323d 100755 --- a/USBComposite.cpp +++ b/USBComposite.cpp @@ -17,7 +17,7 @@ static char* putSerialNumber(char* out, int nibbles, uint32 id) { return out; } -const char* getDeviceIDString() { +char* getDeviceIDString() { static char string[80/4+1]; char* p = string; @@ -41,11 +41,8 @@ USBCompositeDevice::USBCompositeDevice(void) { numParts = 0; setManufacturerString(NULL); setProductString(NULL); - setSerialString(DEFAULT_SERIAL_STRING); - iManufacturer[0] = 0; - iProduct[0] = 0; - iSerialNumber[0] = 0; - } + setSerialString(NULL); +} void USBCompositeDevice::setVendorId(uint16 _vendorId) { if (_vendorId != 0) @@ -61,43 +58,16 @@ void USBCompositeDevice::setProductId(uint16 _productId) { productId = DEFAULT_PRODUCT_ID; } -void setString(uint8* out, const usb_descriptor_string* defaultDescriptor, const char* s, uint32 maxLength) { - if (s == NULL) { - uint8 n = defaultDescriptor->bLength; - uint8 m = USB_DESCRIPTOR_STRING_LEN(maxLength); - if (n > m) - n = m; - memcpy(out, defaultDescriptor, n); - out[0] = n; - } - else { - uint32 n = strlen(s); - if (n > maxLength) - n = maxLength; - out[0] = (uint8)USB_DESCRIPTOR_STRING_LEN(n); - out[1] = USB_DESCRIPTOR_TYPE_STRING; - for (uint32 i=0; i -#define USB_MAX_PRODUCT_LENGTH 32 -#define USB_MAX_MANUFACTURER_LENGTH 32 -#define USB_MAX_SERIAL_NUMBER_LENGTH 20 - +#define USB_COMPOSITE_MAX_PARTS 6 // You could use this for a serial number, but you'll be revealing the device ID to the host, // and hence burning it for cryptographic purposes. -const char* getDeviceIDString(); - -#define USB_COMPOSITE_MAX_PARTS 6 +char* getDeviceIDString(); class USBCompositeDevice; @@ -26,11 +21,9 @@ typedef void(*USBPartStopper)(void*); class USBCompositeDevice { private: - bool enabled = false; - bool haveSerialNumber = false; - uint8_t iManufacturer[USB_DESCRIPTOR_STRING_LEN(USB_MAX_MANUFACTURER_LENGTH)]; - uint8_t iProduct[USB_DESCRIPTOR_STRING_LEN(USB_MAX_PRODUCT_LENGTH)]; - uint8_t iSerialNumber[USB_DESCRIPTOR_STRING_LEN(USB_MAX_SERIAL_NUMBER_LENGTH)]; + const char* iManufacturer = NULL; + const char* iProduct = NULL; + const char* iSerialNumber = NULL; uint16 vendorId; uint16 productId; USBCompositePart* parts[USB_COMPOSITE_MAX_PARTS]; @@ -38,6 +31,7 @@ class USBCompositeDevice { USBPartStopper stop[USB_COMPOSITE_MAX_PARTS]; void* plugin[USB_COMPOSITE_MAX_PARTS]; uint32 numParts; + bool enabled = false; public: USBCompositeDevice(void); void setVendorId(uint16 vendor=0); diff --git a/USBHID.cpp b/USBHID.cpp index e638f3f..7128f87 100644 --- a/USBHID.cpp +++ b/USBHID.cpp @@ -33,6 +33,36 @@ bool USBHID::init(USBHID* me) { usb_hid_setTXEPSize(me->txPacketSize); + + HIDReporter* r = me->profiles; + + if (me->baseChunk.data != NULL) { + /* user set an explicit report for USBHID */ + while (r != NULL) { + r->reportID = r->userSuppliedReportID; + if (r->reportID != 0) + r->reportBuffer[0] = r->reportID; + r = r->next; + } + usb_hid_set_report_descriptor(&(me->baseChunk)); + } + else { + uint8 reportID = HID_AUTO_REPORT_ID_START; + + while (r != NULL) { + if (r->forceUserSuppliedReportID) + r->reportID = r->userSuppliedReportID; + else + r->reportID = reportID++; + + if (r->reportID != 0) + r->reportBuffer[0] = r->reportID; + + r = r->next; + } + usb_hid_set_report_descriptor(me->chunkList); + } + return true; } @@ -41,11 +71,62 @@ bool USBHID::registerComponent() { } void USBHID::setReportDescriptor(const uint8_t* report_descriptor, uint16_t report_descriptor_length) { - usb_hid_set_report_descriptor(report_descriptor, report_descriptor_length); + baseChunk.dataLength = report_descriptor_length; + baseChunk.data = report_descriptor; + baseChunk.next = NULL; +} + +void USBHID::clear() { + clearBuffers(); + baseChunk.data = NULL; + baseChunk.dataLength = 0; + baseChunk.next = NULL; + chunkList = NULL; + profiles = NULL; +} + +void USBHID::addReport(HIDReporter* r, bool always) { + if (! always && ! autoRegister) + return; + + r->next = NULL; + if (profiles == NULL) { + profiles = r; + } + else { + HIDReporter* tail = profiles; + while (tail != r && tail->next != NULL) { + tail = tail->next; + } + if (tail == r) + return; + tail->next = r; + } + + struct usb_chunk* chunkTail = chunkList; + + if (chunkTail == NULL) { + chunkList = &(r->reportChunks[0]); + chunkTail = chunkList; + } + else { + while (chunkTail->next != NULL) + chunkTail = chunkTail->next; + chunkTail->next = &(r->reportChunks[0]); + chunkTail = chunkTail->next; + } + chunkTail->next = &(r->reportChunks[1]); + chunkTail = chunkTail->next; + chunkTail->next = &(r->reportChunks[2]); + chunkTail = chunkTail->next; + chunkTail->next = NULL; } void USBHID::setReportDescriptor(const HIDReportDescriptor* report) { - setReportDescriptor(report->descriptor, report->length); + if (report == NULL) + setReportDescriptor(NULL, 0); + else + setReportDescriptor(report->descriptor, report->length); } void USBHID::begin(const uint8_t* report_descriptor, uint16_t report_descriptor_length) { @@ -64,7 +145,10 @@ void USBHID::begin(const uint8_t* report_descriptor, uint16_t report_descriptor_ } void USBHID::begin(const HIDReportDescriptor* report) { - begin(report->descriptor, report->length); + if (report == NULL) + begin(NULL, 0); + else + begin(report->descriptor, report->length); } void USBHID::setBuffers(uint8_t type, volatile HIDBuffer_t* fb, int count) { @@ -111,7 +195,7 @@ void HIDReporter::sendReport() { // } unsigned toSend = bufferSize; - uint8* b = buffer; + uint8* b = reportBuffer; while (toSend) { unsigned delta = usb_hid_tx(b, toSend); @@ -125,27 +209,98 @@ void HIDReporter::sendReport() { /* flush out to avoid having the pc wait for more data */ usb_hid_tx(NULL, 0); } + +void HIDReporter::registerProfile(bool always) { + for (uint32 i=0; i<3; i++) { + reportChunks[i].data = NULL; + reportChunks[i].dataLength = 0; + } + if (reportDescriptor.descriptor != NULL) { + int32_t reportIDOffset = -1; + if (! forceUserSuppliedReportID) { + uint32_t i = 0; + + /* + * parse bits of beginning of report looking for a single-byte report ID (0x85 ID) + */ + while (i < reportDescriptor.length && reportIDOffset < 0) { + if (reportDescriptor.descriptor[i]==0x85) { + if (i+1 < reportDescriptor.length) + reportIDOffset = i+1; + } + // the lowest 2 bit determine the data length of the tag + if ((reportDescriptor.descriptor[i] & 3) == 3) + i += 5; + else + i += 1 + (reportDescriptor.descriptor[i] & 3); + } + if (i >= reportDescriptor.length) { + forceUserSuppliedReportID = true; + } + } + if (forceUserSuppliedReportID) { + reportChunks[0].data = reportDescriptor.descriptor; + reportChunks[0].dataLength = reportDescriptor.length; + } + else { + reportChunks[0].data = reportDescriptor.descriptor; + reportChunks[0].dataLength = reportIDOffset; + reportChunks[1].data = &(reportID); + reportChunks[1].dataLength = 1; + reportChunks[2].data = reportDescriptor.descriptor+reportIDOffset+1; + reportChunks[2].dataLength = reportDescriptor.length - (reportIDOffset+1); + } + } + HID.addReport(this, always); +} -HIDReporter::HIDReporter(USBHID& _HID, uint8_t* _buffer, unsigned _size, uint8_t _reportID) : HID(_HID) { +HIDReporter::HIDReporter(USBHID& _HID, const HIDReportDescriptor* r, uint8_t* _buffer, unsigned _size, uint8_t _reportID, bool forceReportID) : HID(_HID) { + if (r != NULL) { + memcpy(&reportDescriptor, r, sizeof(reportDescriptor)); + } + else { + reportDescriptor.descriptor = NULL; + reportDescriptor.length = 0; + } + if (_reportID == 0) { - buffer = _buffer+1; + reportBuffer = _buffer+1; bufferSize = _size-1; } else { - buffer = _buffer; + reportBuffer = _buffer; bufferSize = _size; } - memset(buffer, 0, bufferSize); - reportID = _reportID; - if (_size > 0 && reportID != 0) - buffer[0] = _reportID; + memset(reportBuffer, 0, bufferSize); + userSuppliedReportID = _reportID; + + if (_size > 0 && _reportID != 0 && ! forceReportID) { + reportBuffer[0] = _reportID; + forceUserSuppliedReportID = false; + } + else { + forceUserSuppliedReportID = true; + } + + registerProfile(false); } -HIDReporter::HIDReporter(USBHID& _HID, uint8_t* _buffer, unsigned _size) : HID(_HID) { - buffer = _buffer; +HIDReporter::HIDReporter(USBHID& _HID, const HIDReportDescriptor* r, uint8_t* _buffer, unsigned _size) : HID(_HID) { + if (r != NULL) { + memcpy(&reportDescriptor, r, sizeof(reportDescriptor)); + } + else { + reportDescriptor.descriptor = NULL; + reportDescriptor.length = 0; + } + + reportBuffer = _buffer; bufferSize = _size; - memset(buffer, 0, _size); - reportID = 0; + memset(_buffer, 0, _size); + userSuppliedReportID = 0; + forceUserSuppliedReportID = true; + + registerProfile(false); } void HIDReporter::setFeature(uint8_t* in) { diff --git a/USBHID.h b/USBHID.h index 2152bdd..c8082ae 100644 --- a/USBHID.h +++ b/USBHID.h @@ -26,6 +26,11 @@ #define USB_HID_MAX_MANUFACTURER_LENGTH 32 #define USB_HID_MAX_SERIAL_NUMBER_LENGTH 20 +#define HID_MAX_REPORT_CHUNKS 24 + +#define HID_REPORT_ID_NONE -1 +#define HID_REPORT_ID_AUTO -2 + #define HID_MOUSE_REPORT_ID 1 #define HID_KEYBOARD_REPORT_ID 2 #define HID_CONSUMER_REPORT_ID 3 @@ -33,6 +38,8 @@ #define HID_KEYBOARD_ROLLOVER 6 +#define HID_AUTO_REPORT_ID_START 0x80 + #define MACRO_GET_ARGUMENT_2(x, y, ...) y #define MACRO_GET_ARGUMENT_1_WITH_DEFAULT(default, ...) MACRO_GET_ARGUMENT_2(placeholder, ## __VA_ARGS__, default) #define MACRO_ARGUMENT_2_TO_END(skip, ...) __VA_ARGS__ @@ -284,24 +291,53 @@ 0xC0 /* end collection */ typedef struct { - uint8_t* descriptor; + const uint8_t* descriptor; uint16_t length; } HIDReportDescriptor; +extern const HIDReportDescriptor* hidReportMouse; +extern const HIDReportDescriptor* hidReportKeyboard; +extern const HIDReportDescriptor* hidReportJoystick; +extern const HIDReportDescriptor* hidReportKeyboardMouse; +extern const HIDReportDescriptor* hidReportKeyboardJoystick; +extern const HIDReportDescriptor* hidReportKeyboardMouseJoystick; +extern const HIDReportDescriptor* hidReportBootKeyboard; +extern const HIDReportDescriptor* hidReportAbsMouse; +extern const HIDReportDescriptor* hidReportConsumer; + +#define HID_MOUSE hidReportMouse +#define HID_KEYBOARD hidReportKeyboard +#define HID_JOYSTICK hidReportJoystick +#define HID_KEYBOARD_MOUSE hidReportKeyboardMouse +#define HID_KEYBOARD_JOYSTICK hidReportKeyboardJoystick +#define HID_KEYBOARD_MOUSE_JOYSTICK hidReportKeyboardMouseJoystick +#define HID_BOOT_KEYBOARD hidReportBootKeyboard + +class HIDReporter; + class USBHID { private: + bool autoRegister = true; bool enabledHID = false; uint32 txPacketSize = 64; + struct usb_chunk* chunkList; + // baseChunk holds any explicitly specified report descriptor that + // overrides any report descriptors from the chain of registered profiles + struct usb_chunk baseChunk = { 0, 0, 0 }; + HIDReporter* profiles; public: static bool init(USBHID* me); + // add a report to the list ; if always is false, then it only works if autoRegister is true + void addReport(HIDReporter* r, bool always=true); + void clear(); bool registerComponent(); void setReportDescriptor(const uint8_t* report_descriptor, uint16_t report_descriptor_length); - void setReportDescriptor(const HIDReportDescriptor* reportDescriptor); + void setReportDescriptor(const HIDReportDescriptor* reportDescriptor=NULL); // All the strings are zero-terminated ASCII strings. Use NULL for defaults. void begin(const uint8_t* report_descriptor, uint16_t length); - void begin(const HIDReportDescriptor* reportDescriptor); + void begin(const HIDReportDescriptor* reportDescriptor = NULL); void begin(USBCompositeSerial serial, const uint8_t* report_descriptor, uint16_t length); - void begin(USBCompositeSerial serial, const HIDReportDescriptor* reportDescriptor); + void begin(USBCompositeSerial serial, const HIDReportDescriptor* reportDescriptor = NULL); void setBuffers(uint8_t buffers, volatile HIDBuffer_t* fb=NULL, int count=0); // type = HID_REPORT_TYPE_FEATURE or HID_REPORT_TYPE_OUTPUT bool addBuffer(uint8_t type, volatile HIDBuffer_t* buffer); void clearBuffers(uint8_t type); @@ -322,13 +358,22 @@ class USBHID { void setTXPacketSize(uint32 size=64) { txPacketSize = size; } + USBHID(bool _autoRegister=true) { + autoRegister = _autoRegister; + } }; class HIDReporter { private: - uint8_t* buffer; - unsigned bufferSize; + uint8_t* reportBuffer; uint8_t reportID; + uint8_t userSuppliedReportID; + bool forceUserSuppliedReportID; + uint16_t bufferSize; + HIDReportDescriptor reportDescriptor; + struct usb_chunk reportChunks[3]; + class HIDReporter* next; + friend class USBHID; protected: USBHID& HID; @@ -338,13 +383,14 @@ class HIDReporter { // if you use this init function, the buffer starts with a reportID, even if the reportID is zero, // and bufferSize includes the reportID; if reportID is zero, sendReport() will skip the initial // reportID byte - HIDReporter(USBHID& _HID, uint8_t* _buffer, unsigned _size, uint8_t _reportID); + HIDReporter(USBHID& _HID, const HIDReportDescriptor* r, uint8_t* _buffer, unsigned _size, uint8_t _reportID, bool forceReportID=false); // if you use this init function, the buffer has no reportID byte in it - HIDReporter(USBHID& _HID, uint8_t* _buffer, unsigned _size); + HIDReporter(USBHID& _HID, const HIDReportDescriptor* r, uint8_t* _buffer, unsigned _size); uint16_t getFeature(uint8_t* out=NULL, uint8_t poll=1); uint16_t getOutput(uint8_t* out=NULL, uint8_t poll=1); uint16_t getData(uint8_t type, uint8_t* out, uint8_t poll=1); // type = HID_REPORT_TYPE_FEATURE or HID_REPORT_TYPE_OUTPUT void setFeature(uint8_t* feature); + void registerProfile(bool always=true); }; //================================================================================ @@ -362,7 +408,7 @@ class HIDMouse : public HIDReporter { void buttons(uint8_t b); uint8_t reportBuffer[5]; public: - HIDMouse(USBHID& HID, uint8_t reportID=HID_MOUSE_REPORT_ID) : HIDReporter(HID, reportBuffer, sizeof(reportBuffer), reportID), _buttons(0) {} + HIDMouse(USBHID& HID, uint8_t reportID=HID_MOUSE_REPORT_ID) : HIDReporter(HID, hidReportMouse, reportBuffer, sizeof(reportBuffer), reportID), _buttons(0) {} void begin(void); void end(void); void click(uint8_t b = MOUSE_LEFT); @@ -385,7 +431,7 @@ class HIDAbsMouse : public HIDReporter { void buttons(uint8_t b); AbsMouseReport_t report; public: - HIDAbsMouse(USBHID& HID, uint8_t reportID=HID_MOUSE_REPORT_ID) : HIDReporter(HID, (uint8_t*)&report, sizeof(report), reportID) { + HIDAbsMouse(USBHID& HID, uint8_t reportID=HID_MOUSE_REPORT_ID) : HIDReporter(HID, hidReportAbsMouse, (uint8_t*)&report, sizeof(report), reportID) { report.buttons = 0; report.x = 0; report.y = 0; @@ -418,7 +464,7 @@ class HIDConsumer : public HIDReporter { PLAY_OR_PAUSE = 0xCD // see pages 75ff of http://www.usb.org/developers/hidpage/Hut1_12v2.pdf }; - HIDConsumer(USBHID& HID, uint8_t reportID=HID_CONSUMER_REPORT_ID) : HIDReporter(HID, (uint8_t*)&report, sizeof(report), reportID) { + HIDConsumer(USBHID& HID, uint8_t reportID=HID_CONSUMER_REPORT_ID) : HIDReporter(HID, hidReportConsumer, (uint8_t*)&report, sizeof(report), reportID) { report.button = 0; } void begin(void); @@ -484,7 +530,7 @@ class HIDKeyboard : public Print, public HIDReporter { public: HIDKeyboard(USBHID& HID, uint8_t _reportID=HID_KEYBOARD_REPORT_ID) : - HIDReporter(HID, (uint8*)&keyReport, sizeof(KeyReport_t), _reportID), + HIDReporter(HID, hidReportKeyboard, (uint8*)&keyReport, sizeof(KeyReport_t), _reportID), ledData(leds, HID_BUFFER_SIZE(1,_reportID), _reportID, HID_BUFFER_MODE_NO_WAIT), reportID(_reportID) {} @@ -532,7 +578,7 @@ class HIDJoystick : public HIDReporter { inline void send(void) { sendReport(); } - void setManualReportMode(bool manualReport); // in manual report mode, reports only sent when send() is called + void setManualReportMode(bool manualReport); // in manual report mode, report only sent when send() is called bool getManualReportMode(); void begin(void); void end(void); @@ -547,7 +593,7 @@ class HIDJoystick : public HIDReporter { void slider(uint16_t val); void hat(int16_t dir); HIDJoystick(USBHID& HID, uint8_t reportID=HID_JOYSTICK_REPORT_ID) - : HIDReporter(HID, (uint8_t*)&joyReport, sizeof(joyReport), reportID) { + : HIDReporter(HID, hidReportJoystick, (uint8_t*)&joyReport, sizeof(joyReport), reportID) { joyReport.buttons = 0; joyReport.hat = 15; joyReport.x = 512; @@ -580,21 +626,5 @@ templateclass HIDRaw : public HIDReporter { } }; -extern const HIDReportDescriptor* hidReportMouse; -extern const HIDReportDescriptor* hidReportKeyboard; -extern const HIDReportDescriptor* hidReportJoystick; -extern const HIDReportDescriptor* hidReportKeyboardMouse; -extern const HIDReportDescriptor* hidReportKeyboardJoystick; -extern const HIDReportDescriptor* hidReportKeyboardMouseJoystick; -extern const HIDReportDescriptor* hidReportBootKeyboard; - -#define HID_MOUSE hidReportMouse -#define HID_KEYBOARD hidReportKeyboard -#define HID_JOYSTICK hidReportJoystick -#define HID_KEYBOARD_MOUSE hidReportKeyboardMouse -#define HID_KEYBOARD_JOYSTICK hidReportKeyboardJoystick -#define HID_KEYBOARD_MOUSE_JOYSTICK hidReportKeyboardMouseJoystick -#define HID_BOOT_KEYBOARD hidReportBootKeyboard - #endif \ No newline at end of file diff --git a/USBMultiSerial.h b/USBMultiSerial.h index 424f24b..134663a 100755 --- a/USBMultiSerial.h +++ b/USBMultiSerial.h @@ -12,7 +12,7 @@ void usb_multi_serial_ifaceSetupHook0(unsigned, void*); class USBSerialPort : public Stream { public: uint32 txPacketSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE; - const uint32 rxPacketSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE; // currently not changeable + uint32 rxPacketSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE; uint32 port; virtual int available(void);// Changed to virtual @@ -34,11 +34,9 @@ class USBSerialPort : public Stream { uint8 isConnected(); uint8 pending(); - /* void setRXPacketSize(uint32 size=USB_MULTI_SERIAL_DEFAULT_RX_SIZE) { rxPacketSize = size; } - */ void setTXPacketSize(uint32 size=USB_MULTI_SERIAL_DEFAULT_TX_SIZE) { txPacketSize = size; @@ -53,7 +51,7 @@ class USBSerialPort : public Stream { } }; -templateclass USBMultiSerial { +templateclass USBMultiSerial { private: bool enabled = false; uint8 buffers[USB_MULTI_SERIAL_BUFFERS_SIZE(numPorts)]; @@ -80,10 +78,10 @@ template::init); } - static bool init(USBMultiSerial* me) { + static bool init(USBMultiSerial* me) { for (uint8 i=0; ibuffers); #if defined(SERIAL_USB) diff --git a/branchlog.sh b/branchlog.sh new file mode 100644 index 0000000..3647c45 --- /dev/null +++ b/branchlog.sh @@ -0,0 +1 @@ +svn log https://github.com/arpruss/USBComposite_stm32f1/branches/abstracted diff --git a/examples/SignedJoystick/SignedJoystick.ino b/examples/SignedJoystick/SignedJoystick.ino index 324e46f..5d5cf0b 100755 --- a/examples/SignedJoystick/SignedJoystick.ino +++ b/examples/SignedJoystick/SignedJoystick.ino @@ -68,7 +68,7 @@ public: void begin(void) {}; void end(void) {}; HIDSignedJoystick(USBHID& HID, uint8_t reportID=HID_JOYSTICK_REPORT_ID) - : HIDReporter(HID, (uint8_t*)&joyReport, sizeof(joyReport), reportID) { + : HIDReporter(HID, NULL, (uint8_t*)&joyReport, sizeof(joyReport), reportID) { joyReport.buttons = 0; joyReport.hat = 15; joyReport.x = 0; @@ -88,7 +88,7 @@ uint8 signedJoyReportDescriptor[] = { }; void setup() { - HID.setReportDescriptor(signedJoyReportDescriptor,sizeof(signedJoyReportDescriptor)); + HID.setReportDescriptor(signedJoyReportDescriptor, sizeof(signedJoyReportDescriptor)); HID.registerComponent(); USBComposite.begin(); while (!USBComposite); diff --git a/examples/rawhid/send.py b/examples/rawhid/send.py index 13c5a55..63e37d2 100755 --- a/examples/rawhid/send.py +++ b/examples/rawhid/send.py @@ -6,7 +6,7 @@ def sample_handler(data): print("Raw data: {0}".format(data)) -device = hid.HidDeviceFilter(vendor_id = 0x1EAF, product_id = 0x0004).get_devices()[0] +device = hid.HidDeviceFilter(vendor_id = 0x1EAF, product_id = 0x24).get_devices()[0] print(device) device.open() device.set_raw_data_handler(sample_handler) diff --git a/usb_audio.c b/usb_audio.c index 11e589b..1158b87 100644 --- a/usb_audio.c +++ b/usb_audio.c @@ -19,6 +19,7 @@ #include "usb_reg_map.h" #include "libmaple/usb.h" #include +#include #include "usb_audio.h" @@ -31,10 +32,9 @@ #define IO_BUFFER_SIZE 256 #define IO_BUFFER_SIZE_MASK (IO_BUFFER_SIZE - 1) //#define AUDIO_INTERFACE_NUMBER (AUDIO_INTERFACE_OFFSET + usbAUDIOPart.startInterface) +#define AUDIO_ISO_EP_ENDPOINT_INFO (&usbAUDIOPart.endpoints[0]) #define AUDIO_ISO_EP_ADDRESS (usbAUDIOPart.endpoints[0].address) -#define AUDIO_ISO_PMA_BUFFER_SIZE (usbAUDIOPart.endpoints[0].bufferSize / 2) -#define AUDIO_ISO_BUF0_PMA_ADDRESS (usbAUDIOPart.endpoints[0].pmaAddress) -#define AUDIO_ISO_BUF1_PMA_ADDRESS (usbAUDIOPart.endpoints[0].pmaAddress + AUDIO_ISO_PMA_BUFFER_SIZE) +#define AUDIO_ISO_PMA_BUFFER_SIZE (usbAUDIOPart.endpoints[0].pmaSize / 2) /* Tx data */ static volatile uint8 audioBufferTx[IO_BUFFER_SIZE]; @@ -50,6 +50,7 @@ static volatile uint32 audio_rx_head = 0; static volatile uint32 audio_rx_tail = 0; static uint8 usbAudioReceiving; +static volatile int8 transmitting; static uint8 clock_valid = 1; static uint16 sample_rate; static uint8 buffer_size; @@ -73,8 +74,6 @@ static void audioDataTxCb(void); static void audioDataRxCb(void); static void audioUSBReset(void); static RESULT audioUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength); -static uint8_t *audio_get(uint16_t Length); -static uint8_t *audio_set(uint16_t Length); static void (*packet_callback)(uint8) = 0; /* @@ -380,18 +379,22 @@ static const audio_part_config_2 audioPartConfigData2 = { static USBEndpointInfo audioEndpointIN[1] = { { .callback = audioDataTxCb, - .bufferSize = AUDIO_MAX_EP_BUFFER_SIZE, - .type = USB_EP_EP_TYPE_ISO, + .pmaSize = AUDIO_MAX_EP_BUFFER_SIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_ISO, .tx = 1, + .exclusive = 1, // TODO: check if needed? + .doubleBuffer = 1 } }; static USBEndpointInfo audioEndpointOUT[1] = { { .callback = audioDataRxCb, - .bufferSize = AUDIO_MAX_EP_BUFFER_SIZE, - .type = USB_EP_EP_TYPE_ISO, + .pmaSize = AUDIO_MAX_EP_BUFFER_SIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_ISO, .tx = 0, + .exclusive = 1, // TODO: check if needed? + .doubleBuffer = 1 } }; @@ -403,7 +406,7 @@ void usb_audio_setEPSize(uint32_t size) { if (usbAUDIOPart.endpoints == audioEndpointIN) size *= 2; - usbAUDIOPart.endpoints[0].bufferSize = size; + usbAUDIOPart.endpoints[0].pmaSize = size; } #define OUT_BYTE(s,v) out[(uint8*)&(s.v)-(uint8*)&s] @@ -512,7 +515,7 @@ uint32 usb_audio_write_tx_data(const uint8* buf, uint32 len) if (len == 0) return 0; /* no data to send */ - while(usbGenericTransmitting >= 0); + while(transmitting >= 0); uint32 head = audio_tx_head; /* load volatile variable */ uint32 tx_unsent = (head - audio_tx_tail) & IO_BUFFER_SIZE_MASK; @@ -578,43 +581,9 @@ uint32 usb_audio_read_rx_data(uint8* buf, uint32 len) /* Since we're USB FS, this function called once per millisecond */ static void audioDataTxCb(void) { - uint32 tail = audio_tx_tail; /* load volatile variable */ - - uint32 dtog_tx = usb_get_ep_dtog_tx(AUDIO_ISO_EP_ADDRESS); - - usbGenericTransmitting = 1; - - /* copy the bytes from USB Tx buffer to PMA buffer */ - uint32 *dst; - if (dtog_tx) - dst = usb_pma_ptr(AUDIO_ISO_BUF1_PMA_ADDRESS); - else - dst = usb_pma_ptr(AUDIO_ISO_BUF0_PMA_ADDRESS); - - uint16 tmp = 0; - uint16 val; - unsigned i; - for (i = 0; i < buffer_size; i++) { - val = audioBufferTx[tail]; - tail = (tail + 1) & IO_BUFFER_SIZE_MASK; - if (i & 1) { - *dst++ = tmp | (val << 8); - } else { - tmp = val; - } - } - - if (buffer_size & 1) - *dst = tmp; - - audio_tx_tail = tail; /* store volatile variable */ - - usbGenericTransmitting = -1; - - if (dtog_tx) - usb_set_ep_tx_buf1_count(AUDIO_ISO_EP_ADDRESS, buffer_size); - else - usb_set_ep_tx_buf0_count(AUDIO_ISO_EP_ADDRESS, buffer_size); + transmitting = 1; + usb_generic_send_from_circular_buffer_double_buffered(AUDIO_ISO_EP_ENDPOINT_INFO, audioBufferTx, IO_BUFFER_SIZE, buffer_size, &audio_tx_tail); + transmitting = -1; if (packet_callback) packet_callback(buffer_size); @@ -622,31 +591,9 @@ static void audioDataTxCb(void) static void audioDataRxCb(void) { - uint32 head = audio_rx_head; /* load volatile variable */ - - uint32 ep_rx_size = usb_get_ep_rx_count(AUDIO_ISO_EP_ADDRESS); - /* This copy won't overwrite unread bytes as long as there is - * enough room in the USB Rx buffer for next packet */ - uint32 *src = usb_pma_ptr(AUDIO_ISO_BUF0_PMA_ADDRESS); - usbAudioReceiving = 1; - - uint16 tmp = 0; - uint8 val; - uint32 i; - for (i = 0; i < ep_rx_size; i++) { - if (i & 1) { - val = tmp >> 8; - } else { - tmp = *src++; - val = tmp & 0xFF; - } - audioBufferRx[head] = val; - head = (head + 1) & IO_BUFFER_SIZE_MASK; - } - - audio_rx_head = head; /* store volatile variable */ - + uint32 ep_rx_size = usb_generic_read_to_circular_buffer(usbAUDIOPart.endpoints+0, audioBufferRx, + IO_BUFFER_SIZE, &audio_rx_head); usbAudioReceiving = 0; if (packet_callback) @@ -659,85 +606,50 @@ static void audioUSBReset(void) { audio_tx_tail = 0; audio_rx_head = 0; audio_rx_tail = 0; + usbAudioReceiving = 0; + transmitting = -1; if (usbAUDIOPart.endpoints == audioEndpointIN) { /* Setup IN endpoint */ - usb_set_ep_kind(AUDIO_ISO_EP_ADDRESS, USB_EP_EP_KIND_DBL_BUF); - usb_set_ep_tx_buf0_addr(AUDIO_ISO_EP_ADDRESS, AUDIO_ISO_BUF0_PMA_ADDRESS); - usb_set_ep_tx_buf1_addr(AUDIO_ISO_EP_ADDRESS, AUDIO_ISO_BUF1_PMA_ADDRESS); - usb_set_ep_tx_buf0_count(AUDIO_ISO_EP_ADDRESS, AUDIO_ISO_PMA_BUFFER_SIZE); - usb_set_ep_tx_buf1_count(AUDIO_ISO_EP_ADDRESS, AUDIO_ISO_PMA_BUFFER_SIZE); - usb_clear_ep_dtog_tx(AUDIO_ISO_EP_ADDRESS); - usb_clear_ep_dtog_rx(AUDIO_ISO_EP_ADDRESS); - usb_set_ep_tx_stat(AUDIO_ISO_EP_ADDRESS, USB_EP_STAT_TX_VALID); + usb_generic_enable_tx(AUDIO_ISO_EP_ENDPOINT_INFO); } else if (usbAUDIOPart.endpoints == audioEndpointOUT) { /* Setup OUT endpoint */ - usb_set_ep_rx_addr(AUDIO_ISO_EP_ADDRESS, AUDIO_ISO_BUF0_PMA_ADDRESS); - usb_clear_ep_dtog_tx(AUDIO_ISO_EP_ADDRESS); - usb_clear_ep_dtog_rx(AUDIO_ISO_EP_ADDRESS); - usb_set_ep_rx_stat(AUDIO_ISO_EP_ADDRESS, USB_EP_STAT_RX_VALID); + usb_generic_enable_rx(AUDIO_ISO_EP_ENDPOINT_INFO); } } -uint8_t *audio_set(uint16_t Length) { - if (!Length) { - pInformation->Ctrl_Info.Usb_wLength = pInformation->USBwLengths.w; - return NULL; - } - - return NULL; -} - -uint8_t *audio_get(uint16_t Length) { - if (!Length) { - pInformation->Ctrl_Info.Usb_wLength = pInformation->USBwLengths.w; - return NULL; - } - - if (((pInformation->USBwIndex >> 8) & 0xFF) != CLOCK_SOURCE_ID) { - return NULL; - } - - switch (pInformation->USBbRequest) { - case CUR: - switch (Length) { - case 1: - return (uint8_t *)(&clock_valid); - case 2: - return (uint8_t *)(&sample_rate); - case 4: - return (uint8_t *)(&sample_rate_range.min); - default: - break; - } - break; - case RANGE: - return (uint8_t *)(&sample_rate_range); - default: - break; - } - - return NULL; -} - #pragma GCC diagnostic ignored "-Wunused-parameter" static RESULT audioUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength) { - uint8_t *(*CopyRoutine)(uint16_t) = NULL; switch (requestType) { - case 0x21: - CopyRoutine = audio_set; - break; - case 0xA1: - CopyRoutine = audio_get; - break; - default: - return USB_UNSUPPORT; + case 0x21: + usb_generic_control_rx_setup(NULL, wLength, NULL); + return USB_SUCCESS; + + case 0xA1: + if ((wIndex >> 8) == CLOCK_SOURCE_ID) { + switch(request) { + case CUR: + switch(wLength) { + case 1: + usb_generic_control_tx_setup(&clock_valid, 1, NULL); + return USB_SUCCESS; + case 2: + usb_generic_control_tx_setup(&sample_rate, 2, NULL); + return USB_SUCCESS; + case 4: + usb_generic_control_tx_setup(&sample_rate_range.min, 4, NULL); + return USB_SUCCESS; + } + break; + case RANGE: + usb_generic_control_tx_setup(&sample_rate_range, sizeof(sample_rate_range), NULL); + return USB_SUCCESS; + } + } + usb_generic_control_tx_setup(NULL, wLength, NULL); + return USB_SUCCESS; } - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - - return USB_SUCCESS; + return USB_UNSUPPORT; } diff --git a/usb_composite_serial.c b/usb_composite_serial.c index cc7757f..9f679bc 100644 --- a/usb_composite_serial.c +++ b/usb_composite_serial.c @@ -37,8 +37,8 @@ #include "usb_generic.h" #include #include -#include #include +//#include /* Private headers */ #include "usb_lib_globals.h" @@ -51,8 +51,9 @@ #define USB_CDCACM_MANAGEMENT_ENDP (serialEndpoints[CDCACM_ENDPOINT_MANAGEMENT].address) #define USB_CDCACM_TX_ENDP (serialEndpoints[CDCACM_ENDPOINT_TX].address) #define USB_CDCACM_RX_ENDP (serialEndpoints[CDCACM_ENDPOINT_RX].address) - -uint16 GetEPTxAddr(uint8 /*bEpNum*/); +#define USB_CDCACM_MANAGEMENT_ENDPOINT_INFO (&serialEndpoints[CDCACM_ENDPOINT_MANAGEMENT]) +#define USB_CDCACM_TX_ENDPOINT_INFO (&serialEndpoints[CDCACM_ENDPOINT_TX]) +#define USB_CDCACM_RX_ENDPOINT_INFO (&serialEndpoints[CDCACM_ENDPOINT_RX]) /* usb_lib headers */ #include "usb_type.h" @@ -74,6 +75,7 @@ static void vcomDataRxCb(void); * Descriptors */ +static volatile int8 transmitting; static uint32_t txEPSize = 64; static uint32_t rxEPSize = 64; @@ -191,20 +193,20 @@ static const serial_part_config serialPartConfigData = { static USBEndpointInfo serialEndpoints[3] = { { .callback = vcomDataTxCb, - .bufferSize = 64, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = 64, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 1, }, { .callback = NULL, - .bufferSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1, }, { .callback = vcomDataRxCb, - .bufferSize = 64, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = 64, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 0, }, }; @@ -229,16 +231,17 @@ static void getSerialPartDescriptor(uint8* out) { } void composite_cdcacm_setTXEPSize(uint32_t size) { - if (size == 0 || size > 64) + if (size == 0) size = 64; - serialEndpoints[0].bufferSize = size; + serialEndpoints[0].pmaSize = size; txEPSize = size; } void composite_cdcacm_setRXEPSize(uint32_t size) { -// if (size == 0 || size > 64) // must be 64 for reasons unknown - size = 64; - serialEndpoints[2].bufferSize = size; + if (size == 0) + size = 64; + size = usb_generic_roundUpToPowerOf2(size); + serialEndpoints[2].pmaSize = size; rxEPSize = size; } @@ -301,11 +304,6 @@ void composite_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void } } -void composite_cdcacm_putc(char ch) { - while (!composite_cdcacm_tx((uint8*)&ch, 1)) - ; -} - /* This function is non-blocking. * * It copies data from a user buffer into the USB peripheral TX @@ -331,9 +329,9 @@ uint32 composite_cdcacm_tx(const uint8* buf, uint32 len) } vcom_tx_head = head; // store volatile variable - while(usbGenericTransmitting >= 0); + while(transmitting >= 0); - if (usbGenericTransmitting<0) { + if (transmitting < 0) { vcomDataTxCb(); // initiate data transmission } @@ -367,7 +365,7 @@ uint32 composite_cdcacm_rx(uint8* buf, uint32 len) uint32 rx_unread = (vcom_rx_head - tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; // If buffer was emptied to a pre-set value, re-enable the RX endpoint if ( rx_unread <= 64 ) { // experimental value, gives the best performance - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + usb_generic_enable_rx(USB_CDCACM_RX_ENDPOINT_INFO); } return n_copied; } @@ -458,69 +456,22 @@ int composite_cdcacm_get_n_data_bits(void) { */ static void vcomDataTxCb(void) { - uint32 tail = vcom_tx_tail; // load volatile variable - uint32 tx_unsent = (vcom_tx_head - tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; - if (tx_unsent==0) { - if ( (--usbGenericTransmitting)==0) goto flush_vcom; // no more data to send - return; // it was already flushed, keep Tx endpoint disabled - } - usbGenericTransmitting = 1; - // We can only send up to txEPSize bytes in the endpoint. - if (tx_unsent > txEPSize) { - tx_unsent = txEPSize; - } - // copy the bytes from USB Tx buffer to PMA buffer - uint32 *dst = usb_pma_ptr(usbSerialPart.endpoints[CDCACM_ENDPOINT_TX].pmaAddress); - uint16 tmp = 0; - uint16 val; - unsigned i; - for (i = 0; i < tx_unsent; i++) { - val = vcomBufferTx[tail]; - tail = (tail + 1) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; - if (i&1) { - *dst++ = tmp | (val<<8); - } else { - tmp = val; - } - } - if ( tx_unsent&1 ) { - *dst = tmp; - } - vcom_tx_tail = tail; // store volatile variable -flush_vcom: - // enable Tx endpoint - usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, tx_unsent); - usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID); + usb_generic_send_from_circular_buffer(USB_CDCACM_TX_ENDPOINT_INFO, + vcomBufferTx, CDC_SERIAL_TX_BUFFER_SIZE, vcom_tx_head, &vcom_tx_tail, &transmitting); } static void vcomDataRxCb(void) { - uint32 head = vcom_rx_head; // load volatile variable - - uint32 ep_rx_size = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP); - // This copy won't overwrite unread bytes as long as there is - // enough room in the USB Rx buffer for next packet - uint32 *src = usb_pma_ptr(usbSerialPart.endpoints[CDCACM_ENDPOINT_RX].pmaAddress); - uint16 tmp = 0; - uint8 val; - uint32 i; - for (i = 0; i < ep_rx_size; i++) { - if (i&1) { - val = tmp>>8; - } else { - tmp = *src++; - val = tmp&0xFF; - } - vcomBufferRx[head] = val; - head = (head + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; - } + uint32 head = vcom_rx_head; + usb_generic_read_to_circular_buffer(USB_CDCACM_RX_ENDPOINT_INFO, + vcomBufferRx, CDC_SERIAL_RX_BUFFER_SIZE, &head); vcom_rx_head = head; // store volatile variable uint32 rx_unread = (head - vcom_rx_tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; // only enable further Rx if there is enough room to receive one more packet if ( rx_unread < (CDC_SERIAL_RX_BUFFER_SIZE-rxEPSize) ) { - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID); + usb_generic_enable_rx(USB_CDCACM_RX_ENDPOINT_INFO); } if (rx_hook) { @@ -528,31 +479,28 @@ static void vcomDataRxCb(void) } } -static uint8* vcomGetSetLineCoding(uint16 length) { - if (length == 0) { - pInformation->Ctrl_Info.Usb_wLength = sizeof(struct composite_cdcacm_line_coding); - } - return (uint8*)&line_coding; -} - static void serialUSBReset(void) { //VCOM vcom_rx_head = 0; vcom_rx_tail = 0; vcom_tx_head = 0; vcom_tx_tail = 0; + transmitting = -1; } +#pragma GCC diagnostic ignored "-Wunused-parameter" static RESULT serialUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength) { - uint8* (*CopyRoutine)(uint16) = 0; + RESULT ret = USB_UNSUPPORT; if ((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT) && interface == CCI_INTERFACE_OFFSET) { switch (request) { case USBHID_CDCACM_GET_LINE_CODING: - CopyRoutine = vcomGetSetLineCoding; + usb_generic_control_tx_setup(&line_coding, sizeof(line_coding), NULL); + ret = USB_SUCCESS; break; case USBHID_CDCACM_SET_LINE_CODING: - CopyRoutine = vcomGetSetLineCoding; + usb_generic_control_rx_setup(&line_coding, sizeof(line_coding), NULL); + ret = USB_SUCCESS; break; default: break; @@ -564,14 +512,7 @@ static RESULT serialUSBDataSetup(uint8 request, uint8 interface, uint8 requestTy } } - if (CopyRoutine == NULL){ - return USB_UNSUPPORT; - } - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - return USB_SUCCESS; + return ret; } static RESULT serialUSBNoDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex) { diff --git a/usb_composite_serial.h b/usb_composite_serial.h index b78bc24..e049ab3 100644 --- a/usb_composite_serial.h +++ b/usb_composite_serial.h @@ -95,7 +95,6 @@ typedef struct * CDC ACM interface */ -void composite_cdcacm_putc(char ch); uint32 composite_cdcacm_tx(const uint8* buf, uint32 len); uint32 composite_cdcacm_rx(uint8* buf, uint32 len); uint32 composite_cdcacm_peek(uint8* buf, uint32 len); diff --git a/usb_generic.c b/usb_generic.c index 89b30cb..e2bee41 100644 --- a/usb_generic.c +++ b/usb_generic.c @@ -32,13 +32,12 @@ * place else. Nonportable bits really need to be factored out, and * the result made cleaner. */ - -#define MATCHING_ENDPOINT_RANGES // make RX and TX endpoints fall in the same range for each part + +//#define MATCHING_ENDPOINT_RANGES // make RX and TX endpoints fall in the same range for each part #include #include #include -#include #include #include #include @@ -47,7 +46,6 @@ #include -//uint16 GetEPTxAddr(uint8 /*bEpNum*/); /* usb_lib headers */ #include "usb_type.h" @@ -56,8 +54,8 @@ #include "usb_generic.h" -// Are we currently sending an IN packet? -volatile int8 usbGenericTransmitting = -1; +const char DEFAULT_PRODUCT[] = "Maple"; +const char DEFAULT_MANUFACTURER[] = "LeafLabs"; static uint8* usbGetConfigDescriptor(uint16 length); static void usbInit(void); @@ -74,12 +72,29 @@ static void usbSetConfiguration(void); static void usbSetDeviceAddress(void); static uint32 disconnect_delay = 500; // in microseconds +static struct usb_chunk* control_tx_chunk_list = NULL; +static uint8 control_tx_chunk_buffer[USB_EP0_BUFFER_SIZE]; + +static volatile uint8* control_tx_buffer = NULL; +static uint16 control_tx_length = 0; +static volatile uint8* control_tx_done = NULL; +static volatile uint8* control_rx_buffer = NULL; +static uint16 control_rx_length = 0; +static volatile uint8* control_rx_done = NULL; + +uint16 epTypes[4] = { + USB_EP_EP_TYPE_BULK, + USB_EP_EP_TYPE_CONTROL, + USB_EP_EP_TYPE_ISO, + USB_EP_EP_TYPE_INTERRUPT +}; + #define LEAFLABS_ID_VENDOR 0x1EAF #define MAPLE_ID_PRODUCT 0x0024 // was 0x0024 #define USB_DEVICE_CLASS 0x00 #define USB_DEVICE_SUBCLASS 0x00 #define DEVICE_PROTOCOL 0x01 -#define REQUEST_TYPE 0b01100000u +//#define REQUEST_TYPE 0b01100000u #define REQUEST_RECIPIENT 0b00011111u static usb_descriptor_device usbGenericDescriptor_Device = @@ -137,29 +152,22 @@ static DEVICE my_Device_Table = { }; /* Unicode language identifier: 0x0409 is US English */ -static const usb_descriptor_string usbHIDDescriptor_LangID = { +static const usb_descriptor_string usb_LangID = { .bLength = USB_DESCRIPTOR_STRING_LEN(1), .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, .bString = {0x09, 0x04}, }; -#define default_iManufacturer_length 8 -const usb_descriptor_string usb_generic_default_iManufacturer = { - .bLength = USB_DESCRIPTOR_STRING_LEN(default_iManufacturer_length), - .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, - .bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0, 'L', 0, 'a', 0, 'b', 0, 's', 0}, +static USB_DESCRIPTOR_STRING(USB_DESCRIPTOR_STRING_LEN(USB_MAX_STRING_DESCRIPTOR_LENGTH)) string_descriptor_buffer = { + .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING }; -#define default_iProduct_length 5 -const usb_descriptor_string usb_generic_default_iProduct = { - .bLength = USB_DESCRIPTOR_STRING_LEN(default_iProduct_length), - .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING, - .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0}, +static ONE_DESCRIPTOR generic_string_descriptor = { + (uint8*)&string_descriptor_buffer, 0 }; - #define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */ -static DEVICE_PROP my_Device_Property = { +static const DEVICE_PROP my_Device_Property = { .Init = usbInit, .Reset = usbReset, .Process_Status_IN = NOP_Process, @@ -191,10 +199,10 @@ static uint8 numStringDescriptors = 3; #define MAX_STRING_DESCRIPTORS 4 static ONE_DESCRIPTOR String_Descriptor[MAX_STRING_DESCRIPTORS] = { - {(uint8*)&usbHIDDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, - {(uint8*)&usb_generic_default_iManufacturer, USB_DESCRIPTOR_STRING_LEN(default_iManufacturer_length)}, - {(uint8*)&usb_generic_default_iProduct, USB_DESCRIPTOR_STRING_LEN(default_iProduct_length)}, - {NULL, 0}, + {(uint8*)&usb_LangID, USB_DESCRIPTOR_STRING_LEN(1)}, + {(uint8*)DEFAULT_MANUFACTURER, 0}, // a 0 in the length field indicates that we synthesize this from an asciiz string + {(uint8*)DEFAULT_PRODUCT, 0}, + {NULL, 0}, }; static USBCompositePart** parts; @@ -206,13 +214,35 @@ static USER_STANDARD_REQUESTS saved_User_Standard_Requests; static void (*ep_int_in[7])(void); static void (*ep_int_out[7])(void); +static uint8 minimum_address; + +static uint8 acceptable_endpoint_number(unsigned partNum, unsigned endpointNum, uint8 address) { + USBEndpointInfo* ep = &(parts[partNum]->endpoints[endpointNum]); + for (unsigned i = 0 ; i <= partNum ; i++) + for(unsigned j = 0 ; (i < partNum && j < parts[partNum]->numEndpoints) || (i == partNum && j < endpointNum) ; j++) { + USBEndpointInfo* ep1 = &(parts[i]->endpoints[j]); + if (ep1->address != address) + continue; + if (ep1->tx == ep->tx || ep->exclusive || ep1->exclusive || ep1->type != ep->type || ep1->doubleBuffer != ep->doubleBuffer) + return 0; + } + return 1; +} + +static int8 allocate_endpoint_address(unsigned partNum, unsigned endpointNum) { + for (uint8 address = minimum_address ; address < 8 ; address++) + if (acceptable_endpoint_number(partNum, endpointNum, address)) + return address; + return -1; +} + uint8 usb_generic_set_parts(USBCompositePart** _parts, unsigned _numParts) { parts = _parts; numParts = _numParts; unsigned numInterfaces = 0; + minimum_address = 1; + uint8 maxAddress = 0; - unsigned numEndpointsRX = 1; - unsigned numEndpointsTX = 1; uint16 usbDescriptorSize = 0; uint16 pmaOffset = USB_EP0_RX_BUFFER_ADDRESS + USB_EP0_BUFFER_SIZE; @@ -229,46 +259,50 @@ uint8 usb_generic_set_parts(USBCompositePart** _parts, unsigned _numParts) { if (usbDescriptorSize + part->descriptorSize > MAX_USB_DESCRIPTOR_DATA_SIZE) { return 0; } - uint8 nrx = 0; - uint8 ntx = 0; - uint16 pma = 0; USBEndpointInfo* ep = part->endpoints; - for (unsigned j = 0; j < part->numEndpoints ; j++) { - if (ep[j].tx) - ntx++; - else - nrx++; - pma += ep[j].bufferSize; - } - - if (numEndpointsRX + nrx > 8 || numEndpointsTX + ntx > 8 || pmaOffset+pma > PMA_MEMORY_SIZE) { - return 0; - } - for (unsigned j = 0 ; j < part->numEndpoints ; j++) { - ep[j].pmaAddress = pmaOffset; - pmaOffset += ep[j].bufferSize; + int8 address = allocate_endpoint_address(i, j); + if (address < 0) + return 0; + + ep[j].pma = usb_pma_ptr(pmaOffset); + uint32 size = ep[j].pmaSize; + // rx has special length alignment issues + if (ep[j].doubleBuffer) { + if (size <= 124 || ep[j].tx) { + size = (size+3)/4*4; + } + else { + size = (size+63)/64*64; + } + } + else { + if (size <= 62 || ep[j].tx) { + size = (size+1)/2*2; + } + else { + size = (size+31)/32*32; + } + } + pmaOffset += size; + if (pmaOffset > PMA_MEMORY_SIZE) + return 0; if (ep[j].callback == NULL) ep[j].callback = NOP_Process; + ep[j].address = address; if (ep[j].tx) { - ep[j].address = numEndpointsTX; - ep_int_in[numEndpointsTX-1] = ep[j].callback; - numEndpointsTX++; + ep_int_in[address-1] = ep[j].callback; } else { - ep[j].address = numEndpointsRX; - ep_int_out[numEndpointsRX-1] = ep[j].callback; - numEndpointsRX++; + ep_int_out[address-1] = ep[j].callback; } + if (maxAddress < address) + maxAddress = address; } part->getPartDescriptor(usbConfig.descriptorData + usbDescriptorSize); usbDescriptorSize += part->descriptorSize; #ifdef MATCHING_ENDPOINT_RANGES - // make sure endpoint numbers of different parts don't overlap between TX and RX - if (numEndpointsTX>numEndpointsRX) - numEndpointsRX=numEndpointsTX; - else - numEndpointsTX=numEndpointsRX; + minimum_address = maxAddress + 1; #endif } @@ -277,12 +311,12 @@ uint8 usb_generic_set_parts(USBCompositePart** _parts, unsigned _numParts) { usbConfig.Config_Header.wTotalLength = usbDescriptorSize + sizeof(Base_Header); Config_Descriptor.Descriptor_Size = usbConfig.Config_Header.wTotalLength; - my_Device_Table.Total_Endpoint = numEndpointsTX+numEndpointsRX; + my_Device_Table.Total_Endpoint = maxAddress + 1; return 1; } -void usb_generic_set_info( uint16 idVendor, uint16 idProduct, const uint8* iManufacturer, const uint8* iProduct, const uint8* iSerialNumber) { +void usb_generic_set_info(uint16 idVendor, uint16 idProduct, const char* iManufacturer, const char* iProduct, const char* iSerialNumber) { if (idVendor != 0) usbGenericDescriptor_Device.idVendor = idVendor; else @@ -294,18 +328,18 @@ void usb_generic_set_info( uint16 idVendor, uint16 idProduct, const uint8* iManu usbGenericDescriptor_Device.idProduct = MAPLE_ID_PRODUCT; if (iManufacturer == NULL) { - iManufacturer = (uint8*)&usb_generic_default_iManufacturer; + iManufacturer = DEFAULT_MANUFACTURER; } String_Descriptor[1].Descriptor = (uint8*)iManufacturer; - String_Descriptor[1].Descriptor_Size = iManufacturer[0]; + String_Descriptor[1].Descriptor_Size = 0; if (iProduct == NULL) { - iProduct = (uint8*)&usb_generic_default_iProduct; + iProduct = DEFAULT_PRODUCT; } String_Descriptor[2].Descriptor = (uint8*)iProduct; - String_Descriptor[2].Descriptor_Size = iProduct[0]; + String_Descriptor[2].Descriptor_Size = 0; if (iSerialNumber == NULL) { numStringDescriptors = 3; @@ -313,10 +347,10 @@ void usb_generic_set_info( uint16 idVendor, uint16 idProduct, const uint8* iManu } else { String_Descriptor[3].Descriptor = (uint8*)iSerialNumber; - String_Descriptor[3].Descriptor_Size = iSerialNumber[0]; + String_Descriptor[3].Descriptor_Size = 0; numStringDescriptors = 4; usbGenericDescriptor_Device.iSerialNumber = 3; - } + } } void usb_generic_enable(void) { @@ -368,7 +402,7 @@ static void usbInit(void) { USBLIB->irq_mask = USB_ISR_MSK; USB_BASE->CNTR = USBLIB->irq_mask; - nvic_irq_enable(NVIC_USB_LP_CAN_RX0); + usb_generic_enable_interrupts_ep0(); for (unsigned i = 0 ; i < numParts ; i++) if(parts[i]->usbInit != NULL) @@ -379,6 +413,10 @@ static void usbInit(void) { #define BTABLE_ADDRESS 0x00 +static inline uint16 pma_ptr_to_offset(uint32* p) { + return (uint16)(((uint32*)p-(uint32*)USB_PMA_BASE) * 2); +} + static void usbReset(void) { pInformation->Current_Configuration = 0; @@ -398,27 +436,44 @@ static void usbReset(void) { usb_set_ep_rx_count(USB_EP0, USB_EP0_BUFFER_SIZE); usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + for (unsigned i = 1 ; i < 8 ; i++) { + usb_set_ep_rx_stat(i, USB_EP_STAT_RX_DISABLED); + usb_clear_ep_dtog_rx(i); + usb_set_ep_tx_stat(i, USB_EP_STAT_TX_DISABLED); + usb_clear_ep_dtog_tx(i); + } + for (unsigned i = 0 ; i < numParts ; i++) { for (unsigned j = 0 ; j < parts[i]->numEndpoints ; j++) { USBEndpointInfo* e = &(parts[i]->endpoints[j]); uint8 address = e->address; - usb_set_ep_type(address, e->type); - if (parts[i]->endpoints[j].tx) { - usb_set_ep_tx_addr(address, e->pmaAddress); + usb_set_ep_type(address, epTypes[e->type]); + usb_set_ep_kind(address, e->doubleBuffer ? USB_EP_EP_KIND_DBL_BUF : 0); + uint16 pmaOffset = pma_ptr_to_offset(e->pma); + if (e->tx) { + usb_set_ep_tx_addr(address, pmaOffset); usb_set_ep_tx_stat(address, USB_EP_STAT_TX_NAK); - usb_set_ep_rx_stat(address, USB_EP_STAT_RX_DISABLED); + if (e->doubleBuffer) { + usb_set_ep_tx_buf0_addr(address, pmaOffset); + usb_set_ep_tx_buf1_addr(address, pmaOffset+e->pmaSize/2); + usb_set_ep_tx_buf0_count(address, e->pmaSize/2); + usb_set_ep_tx_buf1_count(address, e->pmaSize/2); + } } else { - usb_set_ep_rx_addr(address, e->pmaAddress); - usb_set_ep_rx_count(address, e->bufferSize); - usb_set_ep_rx_stat(address, USB_EP_STAT_RX_VALID); + usb_set_ep_rx_addr(address, pmaOffset); + if (! e->doubleBuffer) { + usb_set_ep_rx_count(address, e->pmaSize); + } + usb_set_ep_rx_stat(address, USB_EP_STAT_RX_VALID); } } if (parts[i]->usbReset != NULL) parts[i]->usbReset(); } - usbGenericTransmitting = -1; + control_rx_length = 0; + control_tx_length = 0; USBLIB->state = USB_ATTACHED; SetDeviceAddress(0); @@ -434,7 +489,7 @@ static void usb_power_down(void) { void usb_generic_disable(void) { /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0 * spec, section 7.1.7.3). */ - nvic_irq_disable(NVIC_USB_LP_CAN_RX0); + usb_generic_disable_interrupts_ep0(); if (BOARD_USB_DISC_DEV != NULL) { gpio_write_bit(BOARD_USB_DISC_DEV, (uint8)(uint32)BOARD_USB_DISC_BIT, 1); @@ -451,15 +506,154 @@ void usb_generic_disable(void) { parts[i]->clear(); } +static uint8* control_data_tx(uint16 length) { + unsigned wOffset = pInformation->Ctrl_Info.Usb_wOffset; + + if (length == 0) { + pInformation->Ctrl_Info.Usb_wLength = control_tx_length - wOffset; + return NULL; + } + + if (control_tx_done && pInformation->USBwLengths.w <= wOffset + pInformation->Ctrl_Info.PacketSize) + *control_tx_done = USB_CONTROL_DONE; // this may be a bit premature, but it's our best try + + if (control_tx_buffer == NULL) + return NULL; + else + return (uint8*)control_tx_buffer + wOffset; +} + +void usb_generic_control_tx_setup(volatile void* buffer, uint16 length, volatile uint8* done) { + control_tx_buffer = buffer; + control_tx_length = length; + control_tx_done = done; + pInformation->Ctrl_Info.CopyData = control_data_tx; + pInformation->Ctrl_Info.Usb_wOffset = 0; + control_data_tx(0); +} + +uint32 usb_generic_chunks_length(struct usb_chunk* chunk) { + uint32 l=0; + + while (chunk != NULL) { + l += chunk->dataLength; + chunk = chunk->next; + } + + return l; +} + +static uint8* control_data_chunk_tx(uint16 length) { + unsigned wOffset = pInformation->Ctrl_Info.Usb_wOffset; + + if (length == 0) { + pInformation->Ctrl_Info.Usb_wLength = usb_generic_chunks_length(control_tx_chunk_list) - wOffset; + + return NULL; + } + + if (control_tx_chunk_list == NULL) { + return NULL; + } + else { + uint32 chunks_offset = 0; + uint32 buf_offset = 0; + + for (struct usb_chunk* chunk = control_tx_chunk_list ; chunk != NULL && chunks_offset < wOffset + length ; chunk = chunk->next ) { + uint32 len = chunk->dataLength; + + if (len == 0) + continue; + + if (wOffset < chunks_offset + len) { + /* need to copy some data from this chunk */ + uint32 start; + if (wOffset <= chunks_offset) { + start = 0; + } + else { + start = wOffset - chunks_offset; + } + + uint32 to_copy; + if (wOffset + length <= chunks_offset + len) { + to_copy = wOffset + length - chunks_offset - start; + } + else { + to_copy = len - start; + } + + memcpy(control_tx_chunk_buffer + buf_offset, chunk->data + start, to_copy); + buf_offset += to_copy; + } + + chunks_offset += len; + } + + return (uint8*)control_tx_chunk_buffer; + } +} + +void usb_generic_control_tx_chunk_setup(struct usb_chunk* chunk) { + control_tx_chunk_list = chunk; + pInformation->Ctrl_Info.CopyData = control_data_chunk_tx; + pInformation->Ctrl_Info.Usb_wOffset = 0; + control_data_chunk_tx(0); +} + + + +static uint8* control_data_rx(uint16 length) { + unsigned wOffset = pInformation->Ctrl_Info.Usb_wOffset; + + if (length ==0) { + uint16 len = pInformation->USBwLengths.w; + if (len > control_rx_length) + len = control_rx_length; + + if (wOffset < len) { + pInformation->Ctrl_Info.Usb_wLength = len - wOffset; + } + else { + pInformation->Ctrl_Info.Usb_wLength = 0; + } + + return NULL; + } + + if (control_rx_done && pInformation->USBwLengths.w <= wOffset + pInformation->Ctrl_Info.PacketSize) { + *control_rx_done = USB_CONTROL_DONE; // this may be a bit premature, but it's our best try + } + + if (control_rx_buffer == NULL) + return NULL; + else + return (uint8*)control_rx_buffer + wOffset; +} + +void usb_generic_control_rx_setup(volatile void* buffer, uint16 length, volatile uint8* done) { + control_rx_buffer = buffer; + control_rx_length = length; + control_rx_done = done; + pInformation->Ctrl_Info.CopyData = control_data_rx; + pInformation->Ctrl_Info.Usb_wOffset = 0; + control_data_rx(0); +} + +void usb_generic_control_descriptor_tx(ONE_DESCRIPTOR* d) { + usb_generic_control_tx_setup(d->Descriptor, d->Descriptor_Size, NULL); +} + static RESULT usbDataSetup(uint8 request) { if ((Type_Recipient & REQUEST_RECIPIENT) == INTERFACE_RECIPIENT) { uint8 interface = pInformation->USBwIndex0; for (unsigned i = 0 ; i < numParts ; i++) { USBCompositePart* p = parts[i]; - if (p->usbDataSetup && p->startInterface <= interface && interface < p->startInterface + p->numInterfaces) + if (p->usbDataSetup && p->startInterface <= interface && interface < p->startInterface + p->numInterfaces) { // uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength return parts[i]->usbDataSetup(request, interface - p->startInterface, pInformation->USBbmRequestType, pInformation->USBwValue0, pInformation->USBwValue1, pInformation->USBwIndex, pInformation->USBwLength); + } } } @@ -518,7 +712,28 @@ static uint8* usbGetStringDescriptor(uint16 length) { if (wValue0 >= numStringDescriptors) { return NULL; } - return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); + + ONE_DESCRIPTOR* d = &String_Descriptor[wValue0]; + if (d->Descriptor_Size != 0) { + return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]); + } + else { + const char* s = (char*)d->Descriptor; + + uint32 i = 0; + + while(*s && i < USB_MAX_STRING_DESCRIPTOR_LENGTH) { + string_descriptor_buffer.bString[i] = (uint8)*s; + s++; + i++; + } + + string_descriptor_buffer.bLength = USB_DESCRIPTOR_STRING_LEN(i); + generic_string_descriptor.Descriptor_Size = string_descriptor_buffer.bLength; + if (length > string_descriptor_buffer.bLength) + length = string_descriptor_buffer.bLength; + return Standard_GetDescriptorData(length, &generic_string_descriptor); + } } @@ -532,22 +747,20 @@ static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) { return USB_SUCCESS; } -void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) { - uint16 *dst = (uint16*)usb_pma_ptr(pma_offset); +void usb_copy_to_pma_ptr(volatile const uint8 *buf, uint16 len, uint32* dst) { uint16 n = len >> 1; uint16 i; for (i = 0; i < n; i++) { - *dst = (uint16)(*buf) | *(buf + 1) << 8; + *(uint16*)dst = (uint16)(*buf) | *(buf + 1) << 8; buf += 2; - dst += 2; + dst++; } if (len & 1) { *dst = *buf; } } -void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { - uint32 *src = (uint32*)usb_pma_ptr(pma_offset); +void usb_copy_from_pma_ptr(volatile uint8 *buf, uint16 len, uint32* src) { uint16 *dst = (uint16*)buf; uint16 n = len >> 1; uint16 i; @@ -559,3 +772,145 @@ void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) { } } +// return bytes read +uint32 usb_generic_read_to_circular_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 circularBufferSize, volatile uint32* headP) { + uint32 head = *headP; + uint32 ep_rx_size = usb_get_ep_rx_count(ep->address); + /* This copy won't overwrite unread bytes as long as there is + * enough room in the USB Rx buffer for next packet */ + volatile uint32 *src = ep->pma; + + for (uint32 i = 0; i < ep_rx_size; i++) { + uint16 tmp = *src++; + buf[head] = (uint8)tmp; + head = (head + 1) % circularBufferSize; + i++; + if (i >= ep_rx_size) { + break; + } + buf[head] = (uint8)(tmp>>8); + head = (head + 1) % circularBufferSize; + } + + *headP = head; + + return ep_rx_size; +} + +// returns number of bytes read +// buf should be uint16-aligned +uint32 usb_generic_read_to_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 bufferSize) { + uint32 ep_rx_size = usb_get_ep_rx_count(ep->address); + if (ep_rx_size > bufferSize) + ep_rx_size = bufferSize; + usb_copy_from_pma_ptr(buf, ep_rx_size, ep->pma); + return ep_rx_size; +} + +uint32 usb_generic_send_from_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 amount) { + if (amount > ep->pmaSize) + amount = ep->pmaSize; + + usb_copy_to_pma_ptr(buf, amount, ep->pma); + usb_set_ep_tx_count(ep->address, amount); + usb_generic_enable_tx(ep); + + return amount; +} + +// transmitting = 1 when transmitting, 0 when done but not flushed, negative when done and flushed +uint32 usb_generic_send_from_circular_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 circularBufferSize, uint32 head, volatile uint32* tailP, volatile int8* transmittingP) { + uint32 tail = *tailP; + int32 amount = (head - tail) % circularBufferSize; + if (amount < 0) { + // wish we could count on % returning a non-negative answer + amount += circularBufferSize; + } + + if (amount==0) { + if (*transmittingP <= 0) { + *transmittingP = -1; + return 0; // it was already flushed, keep Tx endpoint disabled + } + *transmittingP = 0; + goto flush; // no more data to send + } + + *transmittingP = 1; + + if (amount > ep->pmaSize) { + amount = ep->pmaSize; + } + + // copy the bytes from USB Tx buffer to PMA buffer + uint32 *dst = ep->pma; + + for (int32 i = 0; i < amount; i++) { + uint16 low = buf[tail]; + tail = (tail + 1) % circularBufferSize; + i++; + if (i >= amount) { + *dst = low; + break; + } + *dst++ = ((uint16)buf[tail] << 8) | low; + tail = (tail + 1) % circularBufferSize; + } + + *tailP = tail; /* store volatile variable */ + +flush: + // enable Tx endpoint + usb_set_ep_tx_count(ep->address, amount); + usb_generic_enable_tx(ep); + + return amount; +} + + +uint32 usb_generic_send_from_circular_buffer_double_buffered(USBEndpointInfo* ep, volatile uint8* buf, uint32 circularBufferSize, uint32 amount, volatile uint32* tailP) { + uint32 tail = *tailP; /* load volatile variable */ + + uint32 dtog_tx = usb_get_ep_dtog_tx(ep->address); + + /* copy the bytes from USB Tx buffer to PMA buffer */ + uint32 *dst; + if (dtog_tx) + dst = PMA_PTR_BUF1(ep); + else + dst = PMA_PTR_BUF0(ep); + + if (amount > ep->pmaSize / 2) + amount = ep->pmaSize / 2; + + for (uint32 i = 0; i < amount; i++) { + uint16 low = buf[tail]; + tail = (tail + 1) % circularBufferSize; + i++; + if (i >= amount) { + *dst = low; + break; + } + *dst++ = ((uint16)buf[tail] << 8) | low; + tail = (tail + 1) % circularBufferSize; + } + + *tailP = tail; /* store volatile variable */ + + if (dtog_tx) + usb_set_ep_tx_buf1_count(ep->address, amount); + else + usb_set_ep_tx_buf0_count(ep->address, amount); + + return amount; +} + + +uint16_t usb_generic_roundUpToPowerOf2(uint16_t x) { + uint16_t xx; + for (xx = 1 ; xx < x && xx != 0; xx *= 2) ; + if (xx == 0) + return x; + else + return xx; +} diff --git a/usb_generic.h b/usb_generic.h index 24a5157..4246281 100755 --- a/usb_generic.h +++ b/usb_generic.h @@ -3,11 +3,18 @@ #include typedef unsigned short u16; typedef unsigned char u8; -#include + #include +#include +#include +#include "usb_lib_globals.h" +#include "usb_reg_map.h" + +#define USB_CONTROL_DONE 1 #define PMA_MEMORY_SIZE 512 #define MAX_USB_DESCRIPTOR_DATA_SIZE 200 +#define USB_MAX_STRING_DESCRIPTOR_LENGTH 32 #define USB_EP0_BUFFER_SIZE 0x40 #define USB_EP0_TX_BUFFER_ADDRESS 0x40 @@ -17,16 +24,25 @@ typedef unsigned char u8; extern "C" { #endif +enum USB_ENDPOINT_TYPES { + USB_GENERIC_ENDPOINT_TYPE_BULK = 0, + USB_GENERIC_ENDPOINT_TYPE_CONTROL, + USB_GENERIC_ENDPOINT_TYPE_ISO, + USB_GENERIC_ENDPOINT_TYPE_INTERRUPT +}; + extern const usb_descriptor_string usb_generic_default_iManufacturer; extern const usb_descriptor_string usb_generic_default_iProduct; typedef struct USBEndpointInfo { void (*callback)(void); - uint16 bufferSize; - uint16 type; // bulk, interrupt, etc. - uint8 tx; // 1 if TX, 0 if RX + void* pma; + uint16 pmaSize; uint8 address; - uint16 pmaAddress; + uint8 type:2; + uint8 doubleBuffer:1; + uint8 tx:1; // 1 if TX, 0 if RX + uint8 exclusive:1; // 1 if cannot use the same endpoint number for both rx and tx } USBEndpointInfo; typedef struct USBCompositePart { @@ -45,14 +61,89 @@ typedef struct USBCompositePart { USBEndpointInfo* endpoints; } USBCompositePart; +struct usb_chunk { + uint32 dataLength; + const uint8* data; + struct usb_chunk* next; +} __packed; + +uint32 usb_generic_chunks_length(struct usb_chunk* chunk); + +static inline void usb_generic_enable_rx(USBEndpointInfo* ep) { + usb_set_ep_rx_stat(ep->address, USB_EP_STAT_RX_VALID); +} + +static inline void usb_generic_enable_tx(USBEndpointInfo* ep) { + usb_set_ep_tx_stat(ep->address, USB_EP_STAT_TX_VALID); +} + +static inline void usb_generic_stall_rx(USBEndpointInfo* ep) { + usb_set_ep_rx_stat(ep->address, USB_EP_STAT_RX_STALL); +} + +static inline void usb_generic_stall_tx(USBEndpointInfo* ep) { + usb_set_ep_tx_stat(ep->address, USB_EP_STAT_TX_STALL); +} + +static inline void usb_generic_disable_rx(USBEndpointInfo* ep) { + usb_set_ep_rx_stat(ep->address, USB_EP_STAT_RX_DISABLED); +} + +static inline void usb_generic_pause_rx(USBEndpointInfo* ep) { + usb_set_ep_rx_stat(ep->address, USB_EP_STAT_RX_NAK); +} + +static inline void usb_generic_disable_tx(USBEndpointInfo* ep) { + usb_set_ep_tx_stat(ep->address, USB_EP_STAT_TX_DISABLED); +} + +static inline void usb_generic_enable_rx_ep0(void) { + usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); +} + +static inline void usb_generic_pause_rx_ep0(void) { + usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_NAK); +} + +static inline void usb_generic_disable_interrupts_ep0(void) { + nvic_irq_disable(NVIC_USB_LP_CAN_RX0); +} + +static inline void usb_generic_enable_interrupts_ep0(void) { + nvic_irq_enable(NVIC_USB_LP_CAN_RX0); +} + +static inline void usb_generic_prepare_tx(USBEndpointInfo* ep, uint32 length) { + usb_set_ep_tx_count(ep->address, length); +} + +static inline void usb_generic_set_tx(USBEndpointInfo* ep, uint32 length) { + usb_set_ep_tx_count(ep->address, length); + usb_generic_enable_tx(ep); +} + +// for double buffering +#define PMA_PTR_BUF1(ep) ((void*)((uint8*)(ep)->pma+(ep)->pmaSize)) +#define PMA_PTR_BUF0(ep) ((ep)->pma) + +uint32 usb_generic_send_from_circular_buffer_double_buffered(USBEndpointInfo* ep, volatile uint8* buf, uint32 circularBufferSize, uint32 amount, volatile uint32* tailP); void usb_generic_set_disconnect_delay(uint32 delay); -void usb_generic_set_info(uint16 idVendor, uint16 idProduct, const uint8* iManufacturer, const uint8* iProduct, const uint8* iSerialNumber); +void usb_generic_set_info(uint16 idVendor, uint16 idProduct, const char* iManufacturer, const char* iProduct, const char* iSerialNumber); uint8 usb_generic_set_parts(USBCompositePart** _parts, unsigned _numParts); +void usb_generic_control_rx_setup(volatile void* buffer, uint16 length, volatile uint8* done); +void usb_generic_control_tx_setup(volatile void* buffer, uint16 length, volatile uint8* done); +void usb_generic_control_tx_chunk_setup(struct usb_chunk* chunk); +void usb_generic_control_descriptor_tx(ONE_DESCRIPTOR* d); void usb_generic_disable(void); void usb_generic_enable(void); -extern volatile int8 usbGenericTransmitting; -void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset); -void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset); +void usb_copy_from_pma_ptr(volatile uint8 *buf, uint16 len, uint32* pma); +void usb_copy_to_pma_ptr(volatile const uint8 *buf, uint16 len, uint32* pma); +uint32 usb_generic_read_to_circular_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 bufferSize, volatile uint32* headP); +#define USB_GENERIC_UNLIMITED_BUFFER 0xFFFFFFFFul +uint32 usb_generic_read_to_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 bufferSize); +uint32 usb_generic_send_from_circular_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 bufferSize, uint32 head, volatile uint32* tailP, volatile int8* transmittingP); +uint32 usb_generic_send_from_buffer(USBEndpointInfo* ep, volatile uint8* buf, uint32 amount); +uint16_t usb_generic_roundUpToPowerOf2(uint16_t x); #ifdef __cplusplus } diff --git a/usb_hid.c b/usb_hid.c index 9a13871..83fd7d4 100644 --- a/usb_hid.c +++ b/usb_hid.c @@ -33,15 +33,9 @@ * the result made cleaner. */ +#include "usb_generic.h" #include "usb_hid.h" #include -#include -#include -#include - -/* Private headers */ -#include "usb_lib_globals.h" -#include "usb_reg_map.h" uint16 GetEPTxAddr(uint8 /*bEpNum*/); @@ -50,22 +44,22 @@ uint16 GetEPTxAddr(uint8 /*bEpNum*/); #include "usb_core.h" #include "usb_def.h" + +#include +#include + static uint32 ProtocolValue = 0; static uint32 txEPSize = 64; +static volatile int8 transmitting; +static struct usb_chunk* reportDescriptorChunks = NULL; static void hidDataTxCb(void); static void hidUSBReset(void); static void usb_hid_clear(void); static RESULT hidUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength); static RESULT hidUSBNoDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex); -//static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting); -static uint8* HID_GetReportDescriptor(uint16 Length); -static uint8* HID_GetProtocolValue(uint16 Length); static volatile HIDBuffer_t hidBuffers[MAX_HID_BUFFERS] = {{ 0 }}; -static volatile HIDBuffer_t* currentHIDBuffer = NULL; - -//#define DUMMY_BUFFER_SIZE 0x40 // at least as big as a buffer size #define HID_INTERFACE_OFFSET 0x00 #define NUM_HID_ENDPOINTS 1 @@ -77,6 +71,7 @@ static volatile HIDBuffer_t* currentHIDBuffer = NULL; #define HID_ENDPOINT_TX 0 +#define USB_HID_TX_ENDPOINT_INFO (&hidEndpoints[HID_ENDPOINT_TX]) #define USB_HID_TX_ENDP (hidEndpoints[HID_ENDPOINT_TX].address) @@ -114,17 +109,12 @@ static const hid_part_config hidPartConfigData = { .bLength = sizeof(usb_descriptor_endpoint), .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = USB_DESCRIPTOR_ENDPOINT_IN | 0, // PATCH: USB_HID_TX_ENDP - .bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT, + .bmAttributes = USB_EP_TYPE_INTERRUPT, .wMaxPacketSize = 64, //PATCH .bInterval = 0x0A, } }; -static ONE_DESCRIPTOR HID_Report_Descriptor = { - (uint8*)NULL, - 0 -}; - static ONE_DESCRIPTOR HID_Hid_Descriptor = { (uint8*)&hidPartConfigData.HID_Descriptor, sizeof(hidPartConfigData.HID_Descriptor) @@ -133,8 +123,8 @@ static ONE_DESCRIPTOR HID_Hid_Descriptor = { static USBEndpointInfo hidEndpoints[1] = { { .callback = hidDataTxCb, - .bufferSize = 64, - .type = USB_EP_EP_TYPE_INTERRUPT, // TODO: interrupt??? + .pmaSize = 64, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1, } }; @@ -142,7 +132,7 @@ static USBEndpointInfo hidEndpoints[1] = { void usb_hid_setTXEPSize(uint32_t size) { if (size == 0 || size > 64) size = 64; - hidEndpoints[0].bufferSize = size; + hidEndpoints[0].pmaSize = size; txEPSize = size; } @@ -154,8 +144,9 @@ static void getHIDPartDescriptor(uint8* out) { // patch to reflect where the part goes in the descriptor OUT_BYTE(hidPartConfigData, HID_Interface.bInterfaceNumber) += usbHIDPart.startInterface; OUT_BYTE(hidPartConfigData, HIDDataInEndpoint.bEndpointAddress) += USB_HID_TX_ENDP; - OUT_BYTE(hidPartConfigData, HID_Descriptor.descLenL) = (uint8)HID_Report_Descriptor.Descriptor_Size; - OUT_BYTE(hidPartConfigData, HID_Descriptor.descLenH) = (uint8)(HID_Report_Descriptor.Descriptor_Size>>8); + uint16 size = usb_generic_chunks_length(reportDescriptorChunks); + OUT_BYTE(hidPartConfigData, HID_Descriptor.descLenL) = (uint8)size; + OUT_BYTE(hidPartConfigData, HID_Descriptor.descLenH) = (uint8)(size>>8); OUT_16(hidPartConfigData, HIDDataInEndpoint.wMaxPacketSize) = txEPSize; } @@ -184,37 +175,8 @@ static volatile uint32 hid_tx_head = 0; // Read index from hidBufferTx static volatile uint32 hid_tx_tail = 0; -#define CDC_SERIAL_RX_BUFFER_SIZE 256 // must be power of 2 -#define CDC_SERIAL_RX_BUFFER_SIZE_MASK (CDC_SERIAL_RX_BUFFER_SIZE-1) - - - - -void usb_hid_putc(char ch) { - while (!usb_hid_tx((uint8*)&ch, 1)) - ; -} - - /* -static void hidStatusIn() { - if (pInformation->ControlState == WAIT_STATUS_IN) { - if (currentInFeature >= 0) { - if (featureBuffers[currentInFeature].bufferSize == featureBuffers[currentInFeature].currentDataSize) - featureBuffers[currentInFeature].state = HID_BUFFER_UNREAD; - currentInFeature = -1; - } - if (currentOutput >= 0) { - if (outputBuffers[currentOutput].bufferSize == outputBuffers[currentOutput].currentDataSize) - outputBuffers[currentOutput].state = HID_BUFFER_UNREAD; - currentOutput = -1; - } - } -} - */ - -void usb_hid_set_report_descriptor(const uint8* report_descriptor, uint16 report_descriptor_length) { - HID_Report_Descriptor.Descriptor = (uint8*)report_descriptor; - HID_Report_Descriptor.Descriptor_Size = report_descriptor_length; +void usb_hid_set_report_descriptor(struct usb_chunk* chunks) { + reportDescriptorChunks = chunks; } @@ -233,14 +195,13 @@ static volatile HIDBuffer_t* usb_hid_find_buffer(uint8 type, uint8 reportID) { void usb_hid_set_feature(uint8 reportID, uint8* data) { volatile HIDBuffer_t* buffer = usb_hid_find_buffer(HID_REPORT_TYPE_FEATURE, reportID); if (buffer != NULL) { - usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_NAK); + usb_generic_pause_rx_ep0(); unsigned delta = reportID != 0; memcpy((uint8*)buffer->buffer+delta, data, buffer->bufferSize-delta); if (reportID) buffer->buffer[0] = reportID; - buffer->currentDataSize = buffer->bufferSize; buffer->state = HID_BUFFER_READ; - usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + usb_generic_enable_rx_ep0(); return; } } @@ -262,31 +223,26 @@ uint16_t usb_hid_get_data(uint8 type, uint8 reportID, uint8* out, uint8 poll) { if (buffer == NULL) return 0; - nvic_irq_disable(NVIC_USB_LP_CAN_RX0); - + usb_generic_disable_interrupts_ep0(); + if (buffer->reportID == reportID && buffer->state != HID_BUFFER_EMPTY && !(poll && buffer->state == HID_BUFFER_READ)) { - if (buffer->bufferSize != buffer->currentDataSize) { - buffer->state = HID_BUFFER_EMPTY; - ret = 0; + unsigned delta = reportID != 0; + + if (out != NULL) + memcpy(out, (uint8*)buffer->buffer+delta, buffer->bufferSize-delta); + + if (poll) { + buffer->state = HID_BUFFER_READ; } - else { - unsigned delta = reportID != 0; - if (out != NULL) - memcpy(out, (uint8*)buffer->buffer+delta, buffer->bufferSize-delta); - - if (poll) { - buffer->state = HID_BUFFER_READ; - } - ret = buffer->bufferSize-delta; - } + ret = buffer->bufferSize-delta; } if (! have_unread_data_in_hid_buffer() ) { - usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID); + usb_generic_enable_rx_ep0(); } - nvic_irq_enable(NVIC_USB_LP_CAN_RX0); + usb_generic_enable_interrupts_ep0(); return ret; } @@ -339,7 +295,6 @@ void usb_hid_set_buffers(uint8 type, volatile HIDBuffer_t* bufs, int n) { bufs[i].mode |= typeMask; usb_hid_add_buffer(type, bufs+i); } - currentHIDBuffer = NULL; } /* This function is non-blocking. @@ -367,9 +322,9 @@ uint32 usb_hid_tx(const uint8* buf, uint32 len) } hid_tx_head = head; // store volatile variable - while(usbGenericTransmitting >= 0); + while(transmitting >= 0); - if (usbGenericTransmitting<0) { + if (transmitting<0) { hidDataTxCb(); // initiate data transmission } @@ -378,155 +333,35 @@ uint32 usb_hid_tx(const uint8* buf, uint32 len) -uint16 usb_hid_get_pending(void) { +uint32 usb_hid_get_pending(void) { return (hid_tx_head - hid_tx_tail) & HID_TX_BUFFER_SIZE_MASK; } + static void hidDataTxCb(void) { - uint32 tail = hid_tx_tail; // load volatile variable - uint32 tx_unsent = (hid_tx_head - tail) & HID_TX_BUFFER_SIZE_MASK; - if (tx_unsent==0) { - if ( (--usbGenericTransmitting)==0) goto flush_hid; // no more data to send - return; // it was already flushed, keep Tx endpoint disabled - } - usbGenericTransmitting = 1; - // We can only send up to USBHID_CDCACM_TX_EPSIZE bytes in the endpoint. - if (tx_unsent > txEPSize) { - tx_unsent = txEPSize; - } - // copy the bytes from USB Tx buffer to PMA buffer - uint32 *dst = usb_pma_ptr(usbHIDPart.endpoints[HID_ENDPOINT_TX].pmaAddress); - uint16 tmp = 0; - uint16 val; - unsigned i; - for (i = 0; i < tx_unsent; i++) { - val = hidBufferTx[tail]; - tail = (tail + 1) & HID_TX_BUFFER_SIZE_MASK; - if (i&1) { - *dst++ = tmp | (val<<8); - } else { - tmp = val; - } - } - if ( tx_unsent&1 ) { - *dst = tmp; - } - hid_tx_tail = tail; // store volatile variable - -flush_hid: - // enable Tx endpoint - usb_set_ep_tx_count(USB_HID_TX_ENDP, tx_unsent); - usb_set_ep_tx_stat(USB_HID_TX_ENDP, USB_EP_STAT_TX_VALID); + usb_generic_send_from_circular_buffer(USB_HID_TX_ENDPOINT_INFO, + hidBufferTx, HID_TX_BUFFER_SIZE, hid_tx_head, &hid_tx_tail, &transmitting); } - static void hidUSBReset(void) { /* Reset the RX/TX state */ hid_tx_head = 0; hid_tx_tail = 0; - - currentHIDBuffer = NULL; -} - -static uint8* HID_Set(uint16 length) { - if (currentHIDBuffer == NULL) - return NULL; - - if (length ==0) { - if ( (0 == (currentHIDBuffer->mode & HID_BUFFER_MODE_NO_WAIT)) && - currentHIDBuffer->state == HID_BUFFER_UNREAD && - pInformation->Ctrl_Info.Usb_wOffset < pInformation->USBwLengths.w) { - pInformation->Ctrl_Info.Usb_wLength = 0xFFFF; - return NULL; - } - - uint16 len = pInformation->USBwLengths.w; - if (len > currentHIDBuffer->bufferSize) - len = currentHIDBuffer->bufferSize; - - currentHIDBuffer->currentDataSize = len; - - currentHIDBuffer->state = HID_BUFFER_EMPTY; - - if (pInformation->Ctrl_Info.Usb_wOffset < len) { - pInformation->Ctrl_Info.Usb_wLength = len - pInformation->Ctrl_Info.Usb_wOffset; - } - else { - pInformation->Ctrl_Info.Usb_wLength = 0; - } - - return NULL; - } - - if (pInformation->USBwLengths.w <= pInformation->Ctrl_Info.Usb_wOffset + pInformation->Ctrl_Info.PacketSize) { - currentHIDBuffer->state = HID_BUFFER_UNREAD; - } - - return (uint8*)currentHIDBuffer->buffer + pInformation->Ctrl_Info.Usb_wOffset; -} - -static uint8* HID_GetFeature(uint16 length) { - if (currentHIDBuffer == NULL) - return NULL; - - unsigned wOffset = pInformation->Ctrl_Info.Usb_wOffset; - - if (length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = currentHIDBuffer->bufferSize - wOffset; - return NULL; - } - - return (uint8*)currentHIDBuffer->buffer + wOffset; -} - -static uint8* HID_GetReportDescriptor(uint16 Length){ - return Standard_GetDescriptorData(Length, &HID_Report_Descriptor); -} - -static uint8_t *HID_GetHIDDescriptor(uint16_t Length) -{ - return Standard_GetDescriptorData(Length, &HID_Hid_Descriptor); -} - -static uint8* HID_GetProtocolValue(uint16 Length){ - if (Length == 0){ - pInformation->Ctrl_Info.Usb_wLength = 1; - return NULL; - } else { - return (uint8 *)(&ProtocolValue); - } + transmitting = -1; } #pragma GCC diagnostic ignored "-Wunused-parameter" static RESULT hidUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength) { (void)interface; // only one interface - uint8* (*CopyRoutine)(uint16) = 0; - + if ((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { - switch (request) { + switch (request) { case SET_REPORT: - if (wValue1 == HID_REPORT_TYPE_FEATURE) { - volatile HIDBuffer_t* buffer = usb_hid_find_buffer(HID_REPORT_TYPE_FEATURE, wValue0); - - if (buffer == NULL) { - return USB_UNSUPPORT; - } + if (wValue1 == HID_REPORT_TYPE_FEATURE || wValue1 == HID_REPORT_TYPE_OUTPUT) { + volatile HIDBuffer_t* buffer = usb_hid_find_buffer(wValue1, wValue0); - if (0 == (buffer->mode & HID_BUFFER_MODE_NO_WAIT) && buffer->state == HID_BUFFER_UNREAD) { - return USB_NOT_READY; - } - else - { - currentHIDBuffer = buffer; - CopyRoutine = HID_Set; - } - } - else if (wValue1 == HID_REPORT_TYPE_OUTPUT) { - volatile HIDBuffer_t* buffer = usb_hid_find_buffer(HID_REPORT_TYPE_OUTPUT, wValue0); - if (buffer == NULL) { return USB_UNSUPPORT; } @@ -536,9 +371,11 @@ static RESULT hidUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, } else { - currentHIDBuffer = buffer; - CopyRoutine = HID_Set; +// buffer->state = HID_BUFFER_EMPTY; + usb_generic_control_rx_setup(buffer->buffer, buffer->bufferSize, &(buffer->state)); + buffer->state = HID_BUFFER_UNREAD; } + return USB_SUCCESS; } break; case GET_REPORT: @@ -546,58 +383,50 @@ static RESULT hidUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, volatile HIDBuffer_t* buffer = usb_hid_find_buffer(HID_REPORT_TYPE_FEATURE, wValue0); if (buffer == NULL || buffer->state == HID_BUFFER_EMPTY) { - return USB_UNSUPPORT; + return USB_UNSUPPORT; // TODO: maybe UNREADY on empty } - currentHIDBuffer = buffer; - CopyRoutine = HID_GetFeature; - break; + usb_generic_control_tx_setup(buffer->buffer, buffer->bufferSize, NULL); + return USB_SUCCESS; } default: break; } } - - if((requestType & (REQUEST_TYPE | RECIPIENT)) == (STANDARD_REQUEST | INTERFACE_RECIPIENT)){ + + if((requestType & (REQUEST_TYPE | RECIPIENT)) == (STANDARD_REQUEST | INTERFACE_RECIPIENT)){ switch (request){ case GET_DESCRIPTOR: - if (wValue1 == REPORT_DESCRIPTOR){ - CopyRoutine = HID_GetReportDescriptor; - } + if (wValue1 == REPORT_DESCRIPTOR) { + usb_generic_control_tx_chunk_setup(reportDescriptorChunks); + return USB_SUCCESS; + } else if (wValue1 == HID_DESCRIPTOR_TYPE){ - CopyRoutine = HID_GetHIDDescriptor; + usb_generic_control_descriptor_tx(&HID_Hid_Descriptor); + return USB_SUCCESS; } break; case GET_PROTOCOL: - CopyRoutine = HID_GetProtocolValue; - break; + usb_generic_control_tx_setup(&ProtocolValue, 1, NULL); + return USB_SUCCESS; } } - if (CopyRoutine == NULL){ - return USB_UNSUPPORT; - } - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - return USB_SUCCESS; + return USB_UNSUPPORT; } + static RESULT hidUSBNoDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex) { (void)interface; // only one interface - RESULT ret = USB_UNSUPPORT; - if ((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { switch(request) { case SET_PROTOCOL: ProtocolValue = wValue0; - ret = USB_SUCCESS; - break; + return USB_SUCCESS; } } - return ret; + return USB_UNSUPPORT; } diff --git a/usb_hid.h b/usb_hid.h index 4572065..092a7c9 100644 --- a/usb_hid.h +++ b/usb_hid.h @@ -46,7 +46,7 @@ #define HID_BUFFER_MODE_OUTPUT 2 #define HID_BUFFER_EMPTY 0 -#define HID_BUFFER_UNREAD 1 +#define HID_BUFFER_UNREAD USB_CONTROL_DONE #define HID_BUFFER_READ 2 extern USBCompositePart usbHIDPart; @@ -56,7 +56,6 @@ typedef struct HIDBuffer_t { uint16_t bufferSize; // this should match HID_BUFFER_SIZE uint8_t reportID; uint8_t mode; - uint16_t currentDataSize; uint8_t state; // HID_BUFFER_EMPTY, etc. #ifdef __cplusplus inline HIDBuffer_t(volatile uint8_t* _buffer=NULL, uint16_t _bufferSize=0, uint8_t _reportID=0, uint8_t _mode=0) { @@ -72,13 +71,14 @@ typedef struct HIDBuffer_t { extern "C" { #endif -void usb_hid_set_report_descriptor(const uint8* report_descriptor, uint16 report_descriptor_length); +void usb_hid_set_report_descriptor(struct usb_chunk* chunks); void usb_hid_clear_buffers(uint8_t type); uint8_t usb_hid_add_buffer(uint8_t type, volatile HIDBuffer_t* buf); void usb_hid_set_buffers(uint8_t type, volatile HIDBuffer_t* featureBuffers, int count); uint16_t usb_hid_get_data(uint8_t type, uint8_t reportID, uint8_t* out, uint8_t poll); void usb_hid_set_feature(uint8_t reportID, uint8_t* data); void usb_hid_setTXEPSize(uint32_t size); +uint32 usb_hid_get_pending(void); /* * HID Requests @@ -126,8 +126,6 @@ typedef struct } HIDDescriptor; -#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 - #define USB_INTERFACE_CLASS_HID 0x03 #define USB_INTERFACE_SUBCLASS_HID 0x01 @@ -135,12 +133,10 @@ typedef struct * HID interface */ -void usb_hid_putc(char ch); uint32 usb_hid_tx(const uint8* buf, uint32 len); uint32 usb_hid_tx_mod(const uint8* buf, uint32 len); uint32 usb_hid_data_available(void); /* in RX buffer */ -uint16 usb_hid_get_pending(void); #ifdef __cplusplus diff --git a/usb_mass.c b/usb_mass.c index 210cb3d..7c39e60 100644 --- a/usb_mass.c +++ b/usb_mass.c @@ -6,7 +6,6 @@ #include "usb_mass_internal.h" #include -#include #include /* Private headers */ @@ -106,14 +105,14 @@ const mass_descriptor_config usbMassConfigDescriptor = { USBEndpointInfo usbMassEndpoints[2] = { { .callback = usb_mass_in, - .bufferSize = MAX_BULK_PACKET_SIZE, - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = MAX_BULK_PACKET_SIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 1, }, { .callback = usb_mass_out, - .bufferSize = MAX_BULK_PACKET_SIZE, - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = MAX_BULK_PACKET_SIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 0, }, }; @@ -160,8 +159,6 @@ static void usb_mass_reset(void) { static void usb_mass_set_configuration(void) { if (pInformation->Current_Configuration != 0) { deviceState = USB_CONFIGURED; - ClearDTOG_TX(USB_MASS_TX_ENDP); - ClearDTOG_RX(USB_MASS_RX_ENDP); usb_mass_botState = BOT_STATE_IDLE; } } @@ -209,12 +206,6 @@ static uint8_t* usb_mass_get_max_lun(uint16_t length) { static RESULT usb_mass_no_data_setup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex) { if ((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT) && request == REQUEST_MASS_STORAGE_RESET && wValue0 == 0 && wValue1 == 0) { - /* Initialize Endpoint 1 */ - ClearDTOG_TX(USB_MASS_TX_ENDP); - - /* Initialize Endpoint 2 */ - ClearDTOG_RX(USB_MASS_RX_ENDP); - /*initialize the usb_mass_CBW signature to enable the clear feature*/ usb_mass_CBW.dSignature = BOT_CBW_SIGNATURE; usb_mass_botState = BOT_STATE_IDLE; @@ -233,7 +224,7 @@ void usb_mass_loop() { case BOT_STATE_CSW_Send: case BOT_STATE_ERROR: usb_mass_botState = BOT_STATE_IDLE; - SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_VAL); /* enable the Endpoint to receive the next cmd*/ + usb_generic_enable_rx(USB_MASS_RX_ENDPOINT_INFO); /* enable the Endpoint to receive the next cmd*/ break; case BOT_STATE_DATA_IN: switch (usb_mass_CBW.CB[0]) { @@ -401,14 +392,14 @@ static void usb_mass_bot_cbw_decode() { void usb_mass_bot_abort(uint8_t direction) { switch (direction) { case BOT_DIR_IN: - SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_STL); + usb_generic_stall_tx(USB_MASS_TX_ENDPOINT_INFO); break; case BOT_DIR_OUT: - SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_STL); + usb_generic_stall_rx(USB_MASS_RX_ENDPOINT_INFO); break; case BOT_DIR_BOTH: - SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_STL); - SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_STL); + usb_generic_stall_rx(USB_MASS_RX_ENDPOINT_INFO); + usb_generic_stall_tx(USB_MASS_TX_ENDPOINT_INFO); break; default: break; @@ -418,7 +409,6 @@ void usb_mass_bot_abort(uint8_t direction) { void usb_mass_transfer_data_request(uint8_t* dataPointer, uint16_t dataLen) { usb_mass_sil_write(dataPointer, dataLen); - SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_VAL); usb_mass_botState = BOT_STATE_DATA_IN_LAST; usb_mass_CSW.dDataResidue -= dataLen; usb_mass_CSW.bStatus = BOT_CSW_CMD_PASSED; @@ -428,34 +418,21 @@ void usb_mass_bot_set_csw(uint8_t status, uint8_t sendPermission) { usb_mass_CSW.dSignature = BOT_CSW_SIGNATURE; usb_mass_CSW.bStatus = status; - usb_mass_sil_write(((uint8_t *) & usb_mass_CSW), BOT_CSW_DATA_LENGTH); - - usb_mass_botState = BOT_STATE_ERROR; if (sendPermission) { usb_mass_botState = BOT_STATE_CSW_Send; - SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_VAL); + usb_mass_sil_write(((uint8_t *) & usb_mass_CSW), BOT_CSW_DATA_LENGTH); + } + else { + usb_mass_botState = BOT_STATE_ERROR; } } uint32_t usb_mass_sil_write(uint8_t* pBufferPointer, uint32_t wBufferSize) { - /* Use the memory interface function to write to the selected endpoint */ - usb_copy_to_pma(pBufferPointer, wBufferSize, USB_MASS_TX_ADDR); - - /* Update the data length in the control register */ - SetEPTxCount(USB_MASS_TX_ENDP, wBufferSize); + usb_generic_send_from_buffer(USB_MASS_TX_ENDPOINT_INFO, pBufferPointer, wBufferSize); - return 0; + return 0; } uint32_t usb_mass_sil_read(uint8_t* pBufferPointer) { - uint32_t usb_mass_dataLength = 0; - - /* Get the number of received data on the selected Endpoint */ - usb_mass_dataLength = GetEPRxCount(USB_MASS_RX_ENDP); - - /* Use the memory interface function to write to the selected endpoint */ - usb_copy_from_pma(pBufferPointer, usb_mass_dataLength, USB_MASS_RX_ADDR); - - /* Return the number of received data */ - return usb_mass_dataLength; + return usb_generic_read_to_buffer(USB_MASS_RX_ENDPOINT_INFO, pBufferPointer, USB_GENERIC_UNLIMITED_BUFFER); } diff --git a/usb_mass_internal.h b/usb_mass_internal.h index 26967c7..5903827 100755 --- a/usb_mass_internal.h +++ b/usb_mass_internal.h @@ -5,8 +5,10 @@ extern USBEndpointInfo usbMassEndpoints[]; #define MASS_ENDPOINT_TX 0 #define MASS_ENDPOINT_RX 1 +#define USB_MASS_RX_ENDPOINT_INFO (&usbMassEndpoints[MASS_ENDPOINT_RX]) +#define USB_MASS_TX_ENDPOINT_INFO (&usbMassEndpoints[MASS_ENDPOINT_TX]) #define USB_MASS_RX_ENDP (usbMassEndpoints[MASS_ENDPOINT_RX].address) #define USB_MASS_TX_ENDP (usbMassEndpoints[MASS_ENDPOINT_TX].address) -#define USB_MASS_RX_ADDR (usbMassEndpoints[MASS_ENDPOINT_RX].pmaAddress) -#define USB_MASS_TX_ADDR (usbMassEndpoints[MASS_ENDPOINT_TX].pmaAddress) +#define USB_MASS_RX_PMA_PTR (usbMassEndpoints[MASS_ENDPOINT_RX].pma) +#define USB_MASS_TX_PMA_PTR (usbMassEndpoints[MASS_ENDPOINT_TX].pma) #endif \ No newline at end of file diff --git a/usb_midi_device.c b/usb_midi_device.c index 18b944f..41ed5f0 100644 --- a/usb_midi_device.c +++ b/usb_midi_device.c @@ -42,7 +42,6 @@ #include #include -#include #include /* Private headers */ @@ -63,8 +62,10 @@ static void usbMIDIReset(void); #define MIDI_ENDPOINT_TX 1 #define USB_MIDI_RX_ENDP (midiEndpoints[MIDI_ENDPOINT_RX].address) #define USB_MIDI_TX_ENDP (midiEndpoints[MIDI_ENDPOINT_TX].address) -#define USB_MIDI_RX_ADDR (midiEndpoints[MIDI_ENDPOINT_RX].pmaAddress) -#define USB_MIDI_TX_ADDR (midiEndpoints[MIDI_ENDPOINT_TX].pmaAddress) +#define USB_MIDI_RX_ENDPOINT_INFO (&midiEndpoints[MIDI_ENDPOINT_RX]) +#define USB_MIDI_TX_ENDPOINT_INFO (&midiEndpoints[MIDI_ENDPOINT_TX]) +#define USB_MIDI_RX_PMA_PTR (midiEndpoints[MIDI_ENDPOINT_RX].pma) +#define USB_MIDI_TX_PMA_PTR (midiEndpoints[MIDI_ENDPOINT_TX].pma) /* * Descriptors @@ -264,14 +265,14 @@ volatile uint8 myMidiID[] = { LEAFLABS_MMA_VENDOR_1,LEAFLABS_MMA_VENDOR_2,LEAFLA static USBEndpointInfo midiEndpoints[2] = { { .callback = midiDataRxCb, - .bufferSize = 64, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = 64, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 0 }, { .callback = midiDataTxCb, - .bufferSize = 64, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = 64, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 1, } }; @@ -304,7 +305,7 @@ void usb_midi_setTXEPSize(uint32_t size) { size = (size+3)/4*4; if (size == 0 || size > 64) size = 64; - midiEndpoints[1].bufferSize = size; + midiEndpoints[1].pmaSize = size; usb_midi_txEPSize = size; } @@ -312,7 +313,7 @@ void usb_midi_setRXEPSize(uint32_t size) { size = (size+3)/4*4; if (size == 0 || size > 64) size = 64; - midiEndpoints[0].bufferSize = size; + midiEndpoints[0].pmaSize = size; rxEPSize = size; } @@ -341,15 +342,14 @@ uint32 usb_midi_tx(const uint32* buf, uint32 packets) { /* Queue bytes for sending. */ if (packets) { - usb_copy_to_pma((uint8 *)buf, bytes, USB_MIDI_TX_ADDR); + usb_copy_to_pma_ptr((uint8 *)buf, bytes, USB_MIDI_TX_PMA_PTR); } // We still need to wait for the interrupt, even if we're sending // zero bytes. (Sending zero-size packets is useful for flushing // host-side buffers.) - usb_set_ep_tx_count(USB_MIDI_TX_ENDP, bytes); n_unsent_packets = packets; transmitting = 1; - usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_VALID); + usb_generic_set_tx(USB_MIDI_TX_ENDPOINT_INFO, bytes); return packets; } @@ -381,8 +381,7 @@ uint32 usb_midi_rx(uint32* buf, uint32 packets) { /* If all bytes have been read, re-enable the RX endpoint, which * was set to NAK when the current batch of bytes was received. */ if (n_unread_packets == 0) { - usb_set_ep_rx_count(USB_MIDI_RX_ENDP, rxEPSize); - usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID); + usb_generic_enable_rx(USB_MIDI_RX_ENDPOINT_INFO); rx_offset = 0; } @@ -415,21 +414,20 @@ static void midiDataTxCb(void) { } static void midiDataRxCb(void) { - usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_NAK); + usb_generic_pause_rx(USB_MIDI_RX_ENDPOINT_INFO); n_unread_packets = usb_get_ep_rx_count(USB_MIDI_RX_ENDP) / 4; /* This copy won't overwrite unread bytes, since we've set the RX * endpoint to NAK, and will only set it to VALID when all bytes * have been read. */ - usb_copy_from_pma((uint8*)midiBufferRx, n_unread_packets * 4, - USB_MIDI_RX_ADDR); + usb_copy_from_pma_ptr((uint8*)midiBufferRx, n_unread_packets * 4, + USB_MIDI_RX_PMA_PTR); // discard volatile LglSysexHandler((uint32*)midiBufferRx,(uint32*)&rx_offset,(uint32*)&n_unread_packets); if (n_unread_packets == 0) { - usb_set_ep_rx_count(USB_MIDI_RX_ENDP, rxEPSize); - usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID); + usb_generic_enable_rx(USB_MIDI_RX_ENDPOINT_INFO); rx_offset = 0; } diff --git a/usb_midi_device.h b/usb_midi_device.h index b378ce8..ef959d1 100644 --- a/usb_midi_device.h +++ b/usb_midi_device.h @@ -169,7 +169,6 @@ typedef struct { void usb_midi_setTXEPSize(uint32_t size); void usb_midi_setRXEPSize(uint32_t size); -void usb_midi_putc(char ch); uint32 usb_midi_tx(const uint32* buf, uint32 len); uint32 usb_midi_rx(uint32* buf, uint32 len); uint32 usb_midi_peek(uint32* buf, uint32 len); diff --git a/usb_multi_serial.c b/usb_multi_serial.c index 607936d..23d212c 100644 --- a/usb_multi_serial.c +++ b/usb_multi_serial.c @@ -37,7 +37,6 @@ #include "usb_generic.h" #include #include -#include #include /* Private headers */ @@ -60,10 +59,13 @@ #define CDC_SERIAL_TX_BUFFER_SIZE_MASK (CDC_SERIAL_TX_BUFFER_SIZE-1) #define USB_CDCACM_MANAGEMENT_ENDP(port) (serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_MANAGEMENT].address) +#define USB_CDCACM_MANAGEMENT_ENDPOINT_INFO(port) (&serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_MANAGEMENT]) +#define USB_CDCACM_RX_ENDPOINT_INFO(port) (&serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_RX]) +#define USB_CDCACM_TX_ENDPOINT_INFO(port) (&serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_TX]) #define USB_CDCACM_TX_ENDP(port) (serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_TX].address) #define USB_CDCACM_RX_ENDP(port) (serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_RX].address) -#define USB_CDCACM_TX_ADDR(port) (serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_TX].pmaAddress) -#define USB_CDCACM_RX_ADDR(port) (serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_RX].pmaAddress) +#define USB_CDCACM_TX_PMA_PTR(port) (serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_TX].pma) +#define USB_CDCACM_RX_PMA_PTR(port) (serialEndpoints[NUM_SERIAL_ENDPOINTS*(port)+CDCACM_ENDPOINT_RX].pma) /* usb_lib headers */ #include "usb_type.h" @@ -96,6 +98,7 @@ static volatile struct port_data { uint32 vcom_tx_tail; composite_cdcacm_line_coding line_coding; uint8 line_dtr_rts; + int8 transmitting; void (*rx_hook)(unsigned, void*); void (*iface_setup_hook)(unsigned, void*); uint32_t txEPSize; @@ -253,56 +256,56 @@ static const serial_part_config serialPartConfigData = { static USBEndpointInfo serialEndpoints[NUM_SERIAL_ENDPOINTS*USB_MULTI_SERIAL_MAX_PORTS] = { { .callback = vcomDataTxCb0, - .bufferSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 1, }, { .callback = NULL, - .bufferSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1, }, { .callback = vcomDataRxCb0, - .bufferSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 0, }, { .callback = vcomDataTxCb1, - .bufferSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 1, }, { .callback = NULL, - .bufferSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1, }, { .callback = vcomDataRxCb1, - .bufferSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 0, }, { .callback = vcomDataTxCb2, - .bufferSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 1, }, { .callback = NULL, - .bufferSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = USBHID_CDCACM_MANAGEMENT_EPSIZE, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1, }, { .callback = vcomDataRxCb2, - .bufferSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE, // patch - .type = USB_EP_EP_TYPE_BULK, + .pmaSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE, // patch + .type = USB_GENERIC_ENDPOINT_TYPE_BULK, .tx = 0, }, }; @@ -337,17 +340,18 @@ static void getSerialPartDescriptor(uint8* _out) { } void multi_serial_setTXEPSize(uint32 port, uint16_t size) { - if (size == 0 || size > 64) + if (size == 0) size = 64; - serialEndpoints[NUM_SERIAL_ENDPOINTS*port+0].bufferSize = size; + serialEndpoints[NUM_SERIAL_ENDPOINTS*port+0].pmaSize = size; ports[port].txEPSize = size; } void multi_serial_setRXEPSize(uint32 port, uint16_t size) { -// if (size == 0 || size > 64) - size = 64; - serialEndpoints[NUM_SERIAL_ENDPOINTS*port+2].bufferSize = size; - ports[port].rxEPSize = size; + if (size == 0) + size = 64; + size = usb_generic_roundUpToPowerOf2(size); + serialEndpoints[NUM_SERIAL_ENDPOINTS*port+2].pmaSize = size; + ports[port].rxEPSize = size; } USBCompositePart usbMultiSerialPart = { @@ -376,9 +380,9 @@ void multi_serial_initialize_port_data(uint32 _numPorts, uint8* buffers) { p->vcomBufferTx = buffers; buffers += CDC_SERIAL_TX_BUFFER_SIZE; p->vcomBufferRx = buffers; - buffers += CDC_SERIAL_RX_BUFFER_SIZE; p->rxEPSize = USB_MULTI_SERIAL_DEFAULT_RX_SIZE; p->txEPSize = USB_MULTI_SERIAL_DEFAULT_TX_SIZE; + buffers += CDC_SERIAL_RX_BUFFER_SIZE; } usbMultiSerialPart.numInterfaces = NUM_INTERFACES * numPorts; @@ -400,11 +404,6 @@ void multi_serial_set_hooks(uint32 port, unsigned hook_flags, void (*hook)(unsig } } -void multi_serial_putc(uint32 port, char ch) { - while (!multi_serial_tx(port, (uint8*)&ch, 1)) - ; -} - /* This function is non-blocking. * * It copies data from a user buffer into the USB peripheral TX @@ -432,9 +431,9 @@ uint32 multi_serial_tx(uint32 port, const uint8* buf, uint32 len) } p->vcom_tx_head = head; // store volatile variable - while(usbGenericTransmitting >= 0); + while(p->transmitting >= 0); - if (usbGenericTransmitting<0) { + if (p->transmitting < 0) { vcomDataTxCb(port); // initiate data transmission } @@ -471,7 +470,7 @@ uint32 multi_serial_rx(uint32 port, uint8* buf, uint32 len) uint32 rx_unread = (p->vcom_rx_head - tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; // If buffer was emptied to a pre-set value, re-enable the RX endpoint if ( rx_unread <= 64 ) { // experimental value, gives the best performance - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP(port), USB_EP_STAT_RX_VALID); + usb_generic_enable_rx(USB_CDCACM_RX_ENDPOINT_INFO(port)); } return n_copied; } @@ -566,70 +565,23 @@ int multi_serial_get_n_data_bits(uint32 port) { static void vcomDataTxCb(uint32 port) { volatile struct port_data* p = &ports[port]; - uint32 tail = p->vcom_tx_tail; // load volatile variable - uint32 tx_unsent = (p->vcom_tx_head - tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; - if (tx_unsent==0) { - if ( (--usbGenericTransmitting)==0) goto flush_vcom; // no more data to send - return; // it was already flushed, keep Tx endpoint disabled - } - usbGenericTransmitting = 1; - // We can only send up to txEPSize bytes in the endpoint. - if (tx_unsent > p->txEPSize) { - tx_unsent = p->txEPSize; - } - // copy the bytes from USB Tx buffer to PMA buffer - uint32 *dst = usb_pma_ptr(USB_CDCACM_TX_ADDR(port)); - uint16 tmp = 0; - uint16 val; - unsigned i; - for (i = 0; i < tx_unsent; i++) { - val = p->vcomBufferTx[tail]; - tail = (tail + 1) & CDC_SERIAL_TX_BUFFER_SIZE_MASK; - if (i&1) { - *dst++ = tmp | (val<<8); - } else { - tmp = val; - } - } - if ( tx_unsent&1 ) { - *dst = tmp; - } - p->vcom_tx_tail = tail; // store volatile variable -flush_vcom: - // enable Tx endpoint - usb_set_ep_tx_count(USB_CDCACM_TX_ENDP(port), tx_unsent); - usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP(port), USB_EP_STAT_TX_VALID); + usb_generic_send_from_circular_buffer(USB_CDCACM_TX_ENDPOINT_INFO(port), + p->vcomBufferTx, CDC_SERIAL_TX_BUFFER_SIZE, p->vcom_tx_head, &(p->vcom_tx_tail), &(p->transmitting)); } static void vcomDataRxCb(uint32 port) { volatile struct port_data* p = &ports[port]; - uint32 head = p->vcom_rx_head; // load volatile variable - - uint32 ep_rx_size = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP(port)); - // This copy won't overwrite unread bytes as long as there is - // enough room in the USB Rx buffer for next packet - uint32 *src = usb_pma_ptr(USB_CDCACM_RX_ADDR(port)); - uint16 tmp = 0; - uint8 val; - uint32 i; - for (i = 0; i < ep_rx_size; i++) { - if (i&1) { - val = tmp>>8; - } else { - tmp = *src++; - val = tmp&0xFF; - } - p->vcomBufferRx[head] = val; - head = (head + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; - } + uint32 head = p->vcom_rx_head; + usb_generic_read_to_circular_buffer(USB_CDCACM_RX_ENDPOINT_INFO(port), + p->vcomBufferRx, CDC_SERIAL_RX_BUFFER_SIZE, &head); p->vcom_rx_head = head; // store volatile variable uint32 rx_unread = (head - p->vcom_rx_tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK; // only enable further Rx if there is enough room to receive one more packet if ( rx_unread < (CDC_SERIAL_RX_BUFFER_SIZE-p->rxEPSize) ) { - usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP(port), USB_EP_STAT_RX_VALID); + usb_generic_enable_rx(USB_CDCACM_RX_ENDPOINT_INFO(port)); } if (p->rx_hook) { @@ -637,27 +589,6 @@ static void vcomDataRxCb(uint32 port) } } -static uint8* vcomGetSetLineCoding(uint32 port, uint16 length) { - if (length == 0) { - pInformation->Ctrl_Info.Usb_wLength = sizeof(struct composite_cdcacm_line_coding); - } - return (uint8*)&ports[port].line_coding; -} - -static uint8* vcomGetSetLineCoding0(uint16 length) { - return vcomGetSetLineCoding(0, length); -} - -static uint8* vcomGetSetLineCoding1(uint16 length) { - return vcomGetSetLineCoding(1, length); -} - -static uint8* vcomGetSetLineCoding2(uint16 length) { - return vcomGetSetLineCoding(1, length); -} - -static uint8* (*vcomGetSetLineCodings[])(uint16) = { vcomGetSetLineCoding0, vcomGetSetLineCoding1, vcomGetSetLineCoding2 }; - static void serialUSBReset(void) { //VCOM for (uint32 port = 0; portvcom_rx_tail = 0; p->vcom_tx_head = 0; p->vcom_tx_tail = 0; + p->transmitting = -1; } } #pragma GCC diagnostic ignored "-Wunused-parameter" static RESULT serialUSBDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength) { - uint8* (*CopyRoutine)(uint16) = 0; + RESULT ret = USB_UNSUPPORT; if ((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT) && interface % NUM_INTERFACES == CCI_INTERFACE_OFFSET) { uint32 port = interface / NUM_INTERFACES; switch (request) { case USBHID_CDCACM_GET_LINE_CODING: - CopyRoutine = vcomGetSetLineCodings[port]; + usb_generic_control_tx_setup(&ports[port].line_coding, sizeof(ports[port].line_coding), NULL); + ret = USB_SUCCESS; break; case USBHID_CDCACM_SET_LINE_CODING: - CopyRoutine = vcomGetSetLineCodings[port]; + usb_generic_control_rx_setup(&ports[port].line_coding, sizeof(ports[port].line_coding), NULL); + ret = USB_SUCCESS; break; default: break; @@ -692,20 +626,13 @@ static RESULT serialUSBDataSetup(uint8 request, uint8 interface, uint8 requestTy } } - if (CopyRoutine == NULL){ - return USB_UNSUPPORT; - } - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - return USB_SUCCESS; + return ret; } static RESULT serialUSBNoDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex) { RESULT ret = USB_UNSUPPORT; - if ((requestType & (REQUEST_TYPE | RECIPIENT)) && interface % NUM_INTERFACES == CCI_INTERFACE_OFFSET) { + if ((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT) && interface % NUM_INTERFACES == CCI_INTERFACE_OFFSET) { volatile struct port_data* p = &ports[interface / NUM_INTERFACES]; switch(request) { case USBHID_CDCACM_SET_COMM_FEATURE: diff --git a/usb_multi_serial.h b/usb_multi_serial.h index 2a79722..fb22032 100644 --- a/usb_multi_serial.h +++ b/usb_multi_serial.h @@ -44,9 +44,9 @@ extern "C" { #endif #define USB_MULTI_SERIAL_MAX_PORTS 3 -#define USB_MULTI_SERIAL_DEFAULT_RX_SIZE 64 // currently not changeable #define USB_MULTI_SERIAL_DEFAULT_TX_SIZE 24 -#define USB_MULTI_SERIAL_BUFFER_SIZE 256 // must be power of 2 +#define USB_MULTI_SERIAL_DEFAULT_RX_SIZE 64 // must be pwoer of 2 for mysterious reasons +#define USB_MULTI_SERIAL_BUFFER_SIZE 256 // must be power of 2 due to code structure #define USB_MULTI_SERIAL_BUFFERS_SIZE(numPorts) ((numPorts)*2*USB_MULTI_SERIAL_BUFFER_SIZE) void multi_serial_initialize_port_data(uint32 numPorts, uint8* buffers); @@ -57,7 +57,6 @@ extern USBCompositePart usbMultiSerialPart; * CDC ACM interface */ -void multi_serial_putc(uint32 port, char ch); uint32 multi_serial_tx(uint32 port, const uint8* buf, uint32 len); uint32 multi_serial_rx(uint32 port, uint8* buf, uint32 len); uint32 multi_serial_peek(uint32 port, uint8* buf, uint32 len); diff --git a/usb_multi_x360.c b/usb_multi_x360.c index 89a25bf..849e2da 100644 --- a/usb_multi_x360.c +++ b/usb_multi_x360.c @@ -37,7 +37,6 @@ #include #include -#include #include /* Private headers */ @@ -54,7 +53,6 @@ #define USB_ENDPOINT_IN(addr) ((addr) | 0x80) #define HID_ENDPOINT_INT 1 -#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 #define HID_DESCRIPTOR_TYPE 0x21 diff --git a/usb_scsi.c b/usb_scsi.c index e49c75a..b595a2e 100644 --- a/usb_scsi.c +++ b/usb_scsi.c @@ -4,7 +4,6 @@ #include "usb_scsi.h" #include -#include #include /* Private headers */ @@ -164,7 +163,7 @@ void scsi_write10_cmd(uint8_t lun, uint32_t lba, uint32_t blockNbr) { if ((usb_mass_CBW.bmFlags & 0x80) == 0) { usb_mass_botState = BOT_STATE_DATA_OUT; - SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_VAL); + usb_generic_enable_rx(USB_MASS_RX_ENDPOINT_INFO); } else { usb_mass_bot_abort(BOT_DIR_IN); scsi_set_sense_data(usb_mass_CBW.bLUN, SCSI_ILLEGAL_REQUEST, SCSI_INVALID_FIELED_IN_COMMAND); @@ -270,18 +269,16 @@ void scsi_read_memory(uint8_t lun, uint32_t startSector, uint32_t numSectors) { if (SCSI_blockReadCount == 0) { usb_mass_mal_read_memory(lun, SCSI_dataBuffer, (uint32_t)(offset/SCSI_BLOCK_SIZE), 1); - usb_mass_sil_write(SCSI_dataBuffer, MAX_BULK_PACKET_SIZE); - SCSI_blockReadCount = SCSI_BLOCK_SIZE - MAX_BULK_PACKET_SIZE; SCSI_blockOffset = MAX_BULK_PACKET_SIZE; - } else { - usb_mass_sil_write(SCSI_dataBuffer + SCSI_blockOffset, MAX_BULK_PACKET_SIZE); + usb_mass_sil_write(SCSI_dataBuffer, MAX_BULK_PACKET_SIZE); + } else { SCSI_blockReadCount -= MAX_BULK_PACKET_SIZE; SCSI_blockOffset += MAX_BULK_PACKET_SIZE; - } - SetEPTxStatus(USB_MASS_TX_ENDP, USB_EP_ST_TX_VAL); + usb_mass_sil_write(SCSI_dataBuffer + SCSI_blockOffset, MAX_BULK_PACKET_SIZE); + } offset += MAX_BULK_PACKET_SIZE; length -= MAX_BULK_PACKET_SIZE; @@ -328,7 +325,7 @@ void scsi_write_memory(uint8_t lun, uint32_t startSector, uint32_t numSectors) { } usb_mass_CSW.dDataResidue -= usb_mass_dataLength; - SetEPRxStatus(USB_MASS_RX_ENDP, USB_EP_ST_RX_VAL); /* enable the next transaction*/ + usb_generic_enable_rx(USB_MASS_RX_ENDPOINT_INFO); /* enable the next transaction*/ // TODO // TODO: Led_RW_ON(); } diff --git a/usb_x360_generic.c b/usb_x360_generic.c index 68d4fda..2028316 100644 --- a/usb_x360_generic.c +++ b/usb_x360_generic.c @@ -36,7 +36,6 @@ #include #include -#include #include /* Private headers */ @@ -66,7 +65,6 @@ typedef enum _HID_REQUESTS #define USB_ENDPOINT_IN(addr) ((addr) | 0x80) #define HID_ENDPOINT_INT 1 -#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 #define HID_DESCRIPTOR_TYPE 0x21 @@ -224,50 +222,50 @@ typedef struct { USBEndpointInfo x360Endpoints[NUM_ENDPOINTS*USB_X360_MAX_CONTROLLERS] = { { .callback = x360DataTxCb0, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1 }, { .callback = x360DataRxCb0, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 0, }, { .callback = x360DataTxCb1, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1 }, { .callback = x360DataRxCb1, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 0, }, { .callback = x360DataTxCb2, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1 }, { .callback = x360DataRxCb2, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 0, }, { .callback = x360DataTxCb3, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 1 }, { .callback = x360DataRxCb3, - .bufferSize = 0x20, - .type = USB_EP_EP_TYPE_INTERRUPT, + .pmaSize = 0x20, + .type = USB_GENERIC_ENDPOINT_TYPE_INTERRUPT, .tx = 0, }, }; @@ -351,15 +349,14 @@ uint32 x360_tx(uint32 controller, const uint8* buf, uint32 len) { /* Queue bytes for sending. */ if (len) { - usb_copy_to_pma(buf, len, USB_X360_TX_ADDR(controller)); + usb_copy_to_pma_ptr(buf, len, USB_X360_TX_PMA_PTR(controller)); } // We still need to wait for the interrupt, even if we're sending // zero bytes. (Sending zero-size packets is useful for flushing // host-side buffers.) - usb_set_ep_tx_count(USB_X360_TX_ENDP(controller), len); c->n_unsent_bytes = len; c->transmitting = 1; - usb_set_ep_tx_stat(USB_X360_TX_ENDP(controller), USB_EP_STAT_TX_VALID); + usb_generic_set_tx(USB_X360_TX_ENDPOINT_INFO(controller), len); return len; } @@ -367,28 +364,12 @@ uint32 x360_tx(uint32 controller, const uint8* buf, uint32 len) { static void x360DataRxCb(uint32 controller) { volatile struct controller_data* c = &controllers[controller]; - - uint32 rx_endp = USB_X360_RX_ENDP(controller); - uint32 ep_rx_size = usb_get_ep_rx_count(rx_endp); - // This copy won't overwrite unread bytes as long as there is - // enough room in the USB Rx buffer for next packet - uint32 *src = usb_pma_ptr(USB_X360_RX_ADDR(controller)); - uint16 tmp = 0; - uint8 val; - uint32 i; + USBEndpointInfo* ep = USB_X360_RX_ENDPOINT_INFO(controller); volatile uint8* hidBufferRx = c->hidBufferRx; - for (i = 0; i < ep_rx_size; i++) { - if (i&1) { - val = tmp>>8; - } else { - tmp = *src++; - val = tmp&0xFF; - } - hidBufferRx[i] = val; - - } + uint32 ep_rx_size = usb_generic_read_to_buffer(ep, hidBufferRx, USB_X360_RX_EPSIZE); + if (ep_rx_size == 3) { // wired if (c->led_callback != NULL && hidBufferRx[0] == 1 && hidBufferRx[1] == 3) c->led_callback(hidBufferRx[2]); @@ -403,7 +384,8 @@ static void x360DataRxCb(uint32 controller) if (c->rumble_callback != NULL && hidBufferRx[0] == 0 && hidBufferRx[1] == 1) c->rumble_callback(hidBufferRx[5],hidBufferRx[6]); } - usb_set_ep_rx_stat(rx_endp, USB_EP_STAT_RX_VALID); + + usb_generic_enable_rx(ep); } /* @@ -418,23 +400,6 @@ static void x360DataTxCb(uint32 controller) { } -static uint8* HID_GetProtocolValue(uint32 controller, uint16 Length){ - if (Length == 0){ - pInformation->Ctrl_Info.Usb_wLength = 1; - return NULL; - } else { - return (uint8 *)(&controllers[controller].ProtocolValue); - } -} - -static uint8* HID_GetProtocolValue0(uint16 n) { return HID_GetProtocolValue(0, n); } -static uint8* HID_GetProtocolValue1(uint16 n) { return HID_GetProtocolValue(1, n); } -static uint8* HID_GetProtocolValue2(uint16 n) { return HID_GetProtocolValue(2, n); } -static uint8* HID_GetProtocolValue3(uint16 n) { return HID_GetProtocolValue(3, n); } - -static uint8* (*HID_GetProtocolValues[USB_X360_MAX_CONTROLLERS])(uint16 Length) = { HID_GetProtocolValue0, HID_GetProtocolValue1, HID_GetProtocolValue2, HID_GetProtocolValue3 }; - - static void x360Reset(void) { /* Reset the RX/TX state */ for (uint8 i = 0 ; i < x360_num_controllers ; i++) { @@ -446,26 +411,17 @@ static void x360Reset(void) { #pragma GCC diagnostic ignored "-Wunused-parameter" static RESULT x360DataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex, uint16 wLength) { - uint8* (*CopyRoutine)(uint16) = 0; - if((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT) && request == GET_PROTOCOL) { - CopyRoutine = HID_GetProtocolValues[interface / NUM_INTERFACES]; - } - else { - return USB_UNSUPPORT; + usb_generic_control_tx_setup(&controllers[interface / NUM_INTERFACES].ProtocolValue, 1, NULL); + return USB_SUCCESS; } - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - return USB_SUCCESS; + return USB_UNSUPPORT; } static RESULT x360NoDataSetup(uint8 request, uint8 interface, uint8 requestType, uint8 wValue0, uint8 wValue1, uint16 wIndex) { if ((requestType & (REQUEST_TYPE | RECIPIENT)) == (CLASS_REQUEST | INTERFACE_RECIPIENT) && request == SET_PROTOCOL) { controllers[interface / NUM_INTERFACES].ProtocolValue = wValue0; return USB_SUCCESS; - }else{ - return USB_UNSUPPORT; - } + } + return USB_UNSUPPORT; } diff --git a/usb_x360_generic.h b/usb_x360_generic.h index bf2da0e..004736a 100644 --- a/usb_x360_generic.h +++ b/usb_x360_generic.h @@ -71,8 +71,10 @@ void x360_generic_initialize_controller_data(uint32 _numControllers, uint8* buff #define X360_ENDPOINT_RX 1 #define X360_NUM_ENDPOINTS 2 -#define USB_X360_RX_ADDR(i) x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_RX].pmaAddress -#define USB_X360_TX_ADDR(i) x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_TX].pmaAddress +#define USB_X360_RX_ENDPOINT_INFO(i) &x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_RX] +#define USB_X360_TX_ENDPOINT_INFO(i) &x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_TX] +#define USB_X360_RX_PMA_PTR(i) x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_RX].pma +#define USB_X360_TX_PMA_PTR(i) x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_TX].pma #define USB_X360_RX_ENDP(i) x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_RX].address #define USB_X360_TX_ENDP(i) x360Endpoints[(i)*X360_NUM_ENDPOINTS+X360_ENDPOINT_TX].address diff --git a/usb_x360w.c b/usb_x360w.c index a227c27..3cebb19 100644 --- a/usb_x360w.c +++ b/usb_x360w.c @@ -37,7 +37,6 @@ #include #include -#include #include /* Private headers */