int usb_guitar_send(void) { uint32_t wait_count=0; usb_packet_t *tx_packet; //serial_print("send"); //serial_print("\n"); while (1) { if (!usb_configuration) { //serial_print("error1\n"); return -1; } if (usb_tx_packet_count(GUITAR_ENDPOINT1) < TX_PACKET_LIMIT) { tx_packet = usb_malloc(); if (tx_packet) break; } if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { transmit_previous_timeout = 1; //serial_print("error2\n"); return -1; } yield(); } transmit_previous_timeout = 0; memcpy(tx_packet->buf, usb_guitar_data, 7); tx_packet->len = 7; usb_tx(GUITAR_ENDPOINT1, tx_packet); //serial_print("ok\n"); return 0; }
// send the contents of keyboard_keys and keyboard_modifier_keys int usb_keyboard_send(void) { if (!usb_driver_enabled) return 0; uint32_t wait_count=0; usb_packet_t *tx_packet; while (1) { if (!usb_configuration) { return -1; } if (usb_tx_packet_count(KEYBOARD_ENDPOINT) < TX_PACKET_LIMIT) { tx_packet = usb_malloc(); if (tx_packet) break; } if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { transmit_previous_timeout = 1; return -1; } yield(); } *(tx_packet->buf) = keyboard_modifier_keys; *(tx_packet->buf + 1) = keyboard_media_keys; memcpy(tx_packet->buf + 2, keyboard_keys, 6); tx_packet->len = 8; usb_tx(KEYBOARD_ENDPOINT, tx_packet); return 0; }
int usb_serial_write( const void *buffer, uint32_t size ) { uint32_t len; uint32_t wait_count; const uint8_t *src = (const uint8_t *)buffer; uint8_t *dest; tx_noautoflush = 1; while ( size > 0 ) { if ( !tx_packet ) { wait_count = 0; while ( 1 ) { if ( !usb_configuration ) { tx_noautoflush = 0; return -1; } if ( usb_tx_packet_count( CDC_TX_ENDPOINT ) < TX_PACKET_LIMIT ) { tx_noautoflush = 1; tx_packet = usb_malloc(); if ( tx_packet ) break; tx_noautoflush = 0; } if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout ) { transmit_previous_timeout = 1; return -1; } yield(); } } transmit_previous_timeout = 0; len = CDC_TX_SIZE - tx_packet->index; if ( len > size ) len = size; dest = tx_packet->buf + tx_packet->index; tx_packet->index += len; size -= len; while ( len-- > 0 ) *dest++ = *src++; if ( tx_packet->index >= CDC_TX_SIZE ) { tx_packet->len = CDC_TX_SIZE; usb_tx( CDC_TX_ENDPOINT, tx_packet ); tx_packet = NULL; } usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT; } tx_noautoflush = 0; return 0; }
void FlightSimClass::xmit(const void *p1, uint8_t n1, const void *p2, uint8_t n2) { uint16_t total; total = n1 + n2; if (total > FLIGHTSIM_TX_SIZE) { xmit_big_packet(p1, n1, p2, n2); return; } if (!enabled || !usb_configuration) return; tx_noautoflush = 1; if (tx_packet) { if (total <= FLIGHTSIM_TX_SIZE - tx_packet->index) goto send; for (int i = tx_packet->index; i < FLIGHTSIM_TX_SIZE; i++) { tx_packet->buf[i] = 0; } tx_packet->len = FLIGHTSIM_TX_SIZE; usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet); tx_packet = NULL; } while (1) { if (usb_tx_packet_count(FLIGHTSIM_TX_ENDPOINT) < TX_PACKET_LIMIT) { tx_packet = usb_malloc(); if (tx_packet) break; } if (!enabled || !usb_configuration) { tx_noautoflush = 0; return; } tx_noautoflush = 0; yield(); tx_noautoflush = 1; } send: memcpy(tx_packet->buf + tx_packet->index, p1, n1); tx_packet->index += n1; if (n2 > 0) { memcpy(tx_packet->buf + tx_packet->index, p2, n2); tx_packet->index += n2; } if (tx_packet->index >= FLIGHTSIM_TX_SIZE) { tx_packet->len = FLIGHTSIM_TX_SIZE; usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet); tx_packet = NULL; } tx_noautoflush = 0; }
int usb_rawhid_send(const void *buffer, uint32_t timeout) { usb_packet_t *tx_packet; uint32_t begin = millis(); while (1) { if (!usb_configuration) return -1; if (usb_tx_packet_count(RAWHID_TX_ENDPOINT) < TX_PACKET_LIMIT) { tx_packet = usb_malloc(); if (tx_packet) break; } if (millis() - begin > timeout) return 0; yield(); } memcpy(tx_packet->buf, buffer, RAWHID_TX_SIZE); tx_packet->len = RAWHID_TX_SIZE; usb_tx(RAWHID_TX_ENDPOINT, tx_packet); return RAWHID_TX_SIZE; }
// transmit a character. 0 returned on success, -1 on error int usb_serial_putchar(uint8_t c) { #if 1 return usb_serial_write(&c, 1); #endif #if 0 uint32_t wait_count; tx_noautoflush = 1; if (!tx_packet) { wait_count = 0; while (1) { if (!usb_configuration) { tx_noautoflush = 0; return -1; } if (usb_tx_packet_count(CDC_TX_ENDPOINT) < TX_PACKET_LIMIT) { tx_noautoflush = 1; tx_packet = usb_malloc(); if (tx_packet) break; tx_noautoflush = 0; } if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { transmit_previous_timeout = 1; return -1; } } } transmit_previous_timeout = 0; tx_packet->buf[tx_packet->index++] = c; if (tx_packet->index < CDC_TX_SIZE) { usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT; } else { tx_packet->len = CDC_TX_SIZE; usb_cdc_transmit_flush_timer = 0; usb_tx(CDC_TX_ENDPOINT, tx_packet); tx_packet = NULL; } tx_noautoflush = 0; return 0; #endif }
// send the contents of keyboard_keys and keyboard_modifier_keys int usb_keyboard_send(void) { #if 0 serial_print("Send:"); serial_phex(keyboard_modifier_keys); serial_phex(keyboard_keys[0]); serial_phex(keyboard_keys[1]); serial_phex(keyboard_keys[2]); serial_phex(keyboard_keys[3]); serial_phex(keyboard_keys[4]); serial_phex(keyboard_keys[5]); serial_print("\n"); #endif #if 1 uint32_t wait_count=0; usb_packet_t *tx_packet; while (1) { if (!usb_configuration) { return -1; } if (usb_tx_packet_count(KEYBOARD_ENDPOINT) < TX_PACKET_LIMIT) { tx_packet = usb_malloc(); if (tx_packet) break; } if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { transmit_previous_timeout = 1; return -1; } yield(); } *(tx_packet->buf) = keyboard_modifier_keys; *(tx_packet->buf + 1) = keyboard_media_keys; memcpy(tx_packet->buf + 2, keyboard_keys, 6); tx_packet->len = 8; usb_tx(KEYBOARD_ENDPOINT, tx_packet); #endif return 0; }
int usb_serial_write_buffer_free(void) { uint32_t len; tx_noautoflush = 1; if (!tx_packet) { if (!usb_configuration || usb_tx_packet_count(CDC_TX_ENDPOINT) >= TX_PACKET_LIMIT || (tx_packet = usb_malloc()) == NULL) { tx_noautoflush = 0; return 0; } } len = CDC_TX_SIZE - tx_packet->index; // TODO: Perhaps we need "usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT" // added here, so the SOF interrupt can't take away the available buffer // space we just promised the user could write without blocking? // But does this come with other performance downsides? Could it lead to // buffer data never actually transmitting in some usage cases? More // investigation is needed. // https://github.com/PaulStoffregen/cores/issues/10#issuecomment-61514955 tx_noautoflush = 0; return len; }
void FlightSimClass::xmit_big_packet(const void *p1, uint8_t n1, const void *p2, uint8_t n2) { if (!enabled || !usb_configuration) return; uint16_t remaining = n1 + n2; if (remaining > 255) return; bool part2 = false; uint8_t remainingPart1 = n1; const uint8_t *dataPtr = (const uint8_t*)p1; bool writeFragmentHeader = false; uint8_t fragmentCounter = 1; tx_noautoflush =1; // don't mess with my data, I'm working on it! if (tx_packet) { // If we have a current packet, fill it with whatever fits uint8_t partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; if (partLen > n1) partLen=n1; // copy first part, containing total packet length memcpy(tx_packet->buf + tx_packet->index, dataPtr, partLen); remainingPart1 -= partLen; tx_packet->index += partLen; if (remainingPart1) { // there still is data from the first part that // will go to the next packet. The boolean variable // part2 remains false remaining = remainingPart1+n2; dataPtr += partLen; } else { // maybe we have space for some data from the second part part2=true; partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; // there is no need here to check whether partLen is // bigger than n2. It's not. If it were, all the data // would have fit in a single packet and xmit_big_packet // would never have been called... remaining = n2; if (partLen) { memcpy(tx_packet->buf + tx_packet->index, p2, partLen); remaining -= partLen; tx_packet->index += partLen; } dataPtr = (const uint8_t*)p2 + partLen; } // Packet padding should not be necessary, as xmit_big_packet // will only be called for data that doesn't fit in a single // packet. So, the previous code should always fill up the // first packet. Right? for (int i = tx_packet->index; i < FLIGHTSIM_TX_SIZE; i++) { tx_packet->buf[i] = 0; } // queue first packet for sending tx_packet->len = FLIGHTSIM_TX_SIZE; usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet); tx_packet = NULL; writeFragmentHeader = true; } else { remaining = n1+n2; } while (remaining >0) { while (1) { // get memory for next packet if (usb_tx_packet_count(FLIGHTSIM_TX_ENDPOINT) < TX_PACKET_LIMIT) { tx_packet = usb_malloc(); if (tx_packet) { break; } } if (!enabled || !usb_configuration) { // teensy disconnected tx_noautoflush = 0; return; } tx_noautoflush = 0; // you can pick up my data, if you like yield(); // do other things and wait for memory to become free tx_noautoflush = 1; // wait, I'm working on the packet data } if (writeFragmentHeader) { tx_packet->buf[0]=(remaining+3 <= FLIGHTSIM_TX_SIZE) ? (byte) remaining+3 : FLIGHTSIM_TX_SIZE; tx_packet->buf[1]=0xff; tx_packet->buf[2]=fragmentCounter++; tx_packet->index=3; } if (!part2) { // we still need to send the first part uint8_t partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; if (partLen > remainingPart1) partLen=remainingPart1; memcpy(tx_packet->buf + tx_packet->index, dataPtr, partLen); dataPtr += partLen; remainingPart1 -= partLen; tx_packet->index += partLen; remaining -= partLen; if (!remainingPart1) { part2=true; dataPtr = (const uint8_t*)p2; } } if (part2) { uint8_t partLen = FLIGHTSIM_TX_SIZE - tx_packet->index; if (partLen) { if (partLen > remaining) partLen=remaining; memcpy(tx_packet->buf + tx_packet->index, dataPtr, partLen); remaining -= partLen; tx_packet->index += partLen; dataPtr += partLen; } } writeFragmentHeader = true; if (tx_packet->index >= FLIGHTSIM_TX_SIZE) { // queue packet for sending tx_packet->len = FLIGHTSIM_TX_SIZE; usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet); tx_packet = NULL; } } tx_noautoflush = 0; // data is ready to be transmitted on start of USB token }
// send the contents of keyboard_keys and keyboard_modifier_keys void usb_keyboard_send() { uint32_t wait_count = 0; usb_packet_t *tx_packet; // Wait till ready while ( 1 ) { if ( !usb_configuration ) { erro_print("USB not configured..."); return; } if ( USBKeys_Protocol == 0 ) // Boot Mode { if ( usb_tx_packet_count( NKRO_KEYBOARD_ENDPOINT ) < TX_PACKET_LIMIT ) { tx_packet = usb_malloc(); if ( tx_packet ) break; } } else if ( USBKeys_Protocol == 1 ) // NKRO Mode { if ( usb_tx_packet_count( KEYBOARD_ENDPOINT ) < TX_PACKET_LIMIT ) { tx_packet = usb_malloc(); if ( tx_packet ) break; } } if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout ) { transmit_previous_timeout = 1; warn_print("USB Transmit Timeout..."); return; } yield(); } // Pointer to USB tx packet buffer uint8_t *tx_buf = tx_packet->buf; switch ( USBKeys_Protocol ) { // Send boot keyboard interrupt packet(s) case 0: // USB Boot Mode debug output if ( Output_DebugMode ) { dbug_msg("Boot USB: "); printHex_op( USBKeys_Modifiers, 2 ); print(" "); printHex( 0 ); print(" "); printHex_op( USBKeys_Keys[0], 2 ); printHex_op( USBKeys_Keys[1], 2 ); printHex_op( USBKeys_Keys[2], 2 ); printHex_op( USBKeys_Keys[3], 2 ); printHex_op( USBKeys_Keys[4], 2 ); printHex_op( USBKeys_Keys[5], 2 ); print( NL ); } // Boot Mode *tx_buf++ = USBKeys_Modifiers; *tx_buf++ = 0; memcpy( tx_buf, USBKeys_Keys, USB_BOOT_MAX_KEYS ); tx_packet->len = 8; // Send USB Packet usb_tx( KEYBOARD_ENDPOINT, tx_packet ); USBKeys_Changed = USBKeyChangeState_None; break; // Send NKRO keyboard interrupts packet(s) case 1: if ( Output_DebugMode ) { dbug_msg("NKRO USB: "); } // Check system control keys if ( USBKeys_Changed & USBKeyChangeState_System ) { if ( Output_DebugMode ) { print("SysCtrl["); printHex_op( USBKeys_SysCtrl, 2 ); print( "] " NL ); } *tx_buf++ = 0x02; // ID *tx_buf = USBKeys_SysCtrl; tx_packet->len = 2; // Send USB Packet usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); USBKeys_Changed &= ~USBKeyChangeState_System; // Mark sent } // Check consumer control keys if ( USBKeys_Changed & USBKeyChangeState_Consumer ) { if ( Output_DebugMode ) { print("ConsCtrl["); printHex_op( USBKeys_ConsCtrl, 2 ); print( "] " NL ); } *tx_buf++ = 0x03; // ID *tx_buf++ = (uint8_t)(USBKeys_ConsCtrl & 0x00FF); *tx_buf = (uint8_t)(USBKeys_ConsCtrl >> 8); tx_packet->len = 3; // Send USB Packet usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); USBKeys_Changed &= ~USBKeyChangeState_Consumer; // Mark sent } // Standard HID Keyboard if ( USBKeys_Changed ) { // USB NKRO Debug output if ( Output_DebugMode ) { printHex_op( USBKeys_Modifiers, 2 ); print(" "); for ( uint8_t c = 0; c < 6; c++ ) printHex_op( USBKeys_Keys[ c ], 2 ); print(" "); for ( uint8_t c = 6; c < 20; c++ ) printHex_op( USBKeys_Keys[ c ], 2 ); print(" "); printHex_op( USBKeys_Keys[20], 2 ); print(" "); for ( uint8_t c = 21; c < 27; c++ ) printHex_op( USBKeys_Keys[ c ], 2 ); print( NL ); } tx_packet->len = 0; // Modifiers *tx_buf++ = 0x01; // ID *tx_buf++ = USBKeys_Modifiers; tx_packet->len += 2; // 4-49 (first 6 bytes) memcpy( tx_buf, USBKeys_Keys, 6 ); tx_buf += 6; tx_packet->len += 6; // 51-155 (Middle 14 bytes) memcpy( tx_buf, USBKeys_Keys + 6, 14 ); tx_buf += 14; tx_packet->len += 14; // 157-164 (Next byte) memcpy( tx_buf, USBKeys_Keys + 20, 1 ); tx_buf += 1; tx_packet->len += 1; // 176-221 (last 6 bytes) memcpy( tx_buf, USBKeys_Keys + 21, 6 ); tx_packet->len += 6; // Send USB Packet usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet ); USBKeys_Changed = USBKeyChangeState_None; // Mark sent } break; } return; }