/** * Initialises an HID device. * * @param device the USB device. * @param handle configuration information. */ static void hid_initUsb(usb_device * device, hid_usbConfiguration * handle) { // Initialise/configure the USB device. usb_initDevice(device, handle->configuration); #ifdef DEBUG usb_printDeviceInfo( device ); #endif // Initialise bulk / interrupt input endpoint. usb_initEndPoint(&(device->bulk_in), handle->inputEndPointAddress); device->bulk_in.attributes = USB_ENDPOINT_XFER_INT; device->bulk_in.maxPacketSize = HID_USB_PACKETSIZE; // Initialise bulk / interrupt output endpoint. usb_initEndPoint(&(device->bulk_out), handle->outputEndPointAddress); device->bulk_out.attributes = USB_ENDPOINT_XFER_INT; device->bulk_out.maxPacketSize = HID_USB_PACKETSIZE; #ifdef DEBUG xSerialPrintf_P(PSTR("handle->inputEndPointAddress: 0x%02x\r\n"), handle->inputEndPointAddress); xSerialPrintf_P(PSTR("handle->outputEndPointAddress: 0x%02x\r\n"), handle->outputEndPointAddress); xSerialPrintf_P(PSTR("bulk_in.address: 0x%02x\r\n"), device->bulk_in.address); xSerialPrintf_P(PSTR("bulk_out.address: 0x%02x\r\n"), device->bulk_out.address); #endif }
/** @brief Send ping reply packet to the specified peer If Error is occurred in sending ping reply packet, then ignored\n Because it is not need to send ping reply packet to the specified peer every time. */ static void SendPingReply( PING_MSG *pingrequest, /**< received ping reply packet from the specified peer */ uint32_t destaddr /**< 32bit peer ip address (network ordering) */ ) { SOCKET PingReplySocket; PingReplySocket = getSocket(SOCK_CLOSED,0); // Find free socket number if(PingReplySocket != MAX_SOCK_NUM ) // Is there a free socket? { setSn_PROTO( PingReplySocket, IP_PROTO_ICMP); // Set upper protocol of IP_RAW mode if( socket( PingReplySocket, Sn_MR_IPRAW, 3001, 0) != 0) // Open ICMP socket { (*pingrequest).type = 0; // Ping-Reply (*pingrequest).code = 0; // Always 0 (*pingrequest).checksum = 0; (*pingrequest).checksum = htons( checksum((uint8_t*)pingrequest, sizeof(PING_MSG))); // Calculate checksum if(sendto( PingReplySocket, (uint8_t *)pingrequest, sizeof(PING_MSG), (uint8_t*)&destaddr, 3001) == 0) // sent ping-reply packet to the specified peer xSerialPrintf_P(PSTR("Fail to send ping-reply packet to %s. Send failure"),inet_ntoa(ntohl(destaddr))); close(PingReplySocket); // Close ICMP socket } setSn_PROTO(PingReplySocket,0); // Clear IP protocol register. } else xSerialPrintf_P(PSTR("Fail to send ping-reply packet to %s. NO FREE SOCKET"),inet_ntoa(ntohl(destaddr))); }
/** * @brief Initialise the socket & buffer for HTTP server */ uint8_t init_httpd_ch(SOCKET s) { uint8_t ret; ret = 0; if( getSn_SR(s) != SOCK_CLOSED ) // Check the preferred socket is available, { s = getSocket(SOCK_CLOSED, 0); // otherwise find free socket, if(s == MAX_SOCK_NUM ) // If there is no free socket? ret = 0; } else { ret = 1; } if(!socket(s, Sn_MR_TCP, IP_PORT_HTTP, 0x00)) // initialise the socket for DHCP service { xSerialPrintf_P(PSTR("HTTPD socket: %d, initialise fail..!\r\n"),s); ret = 0; } #ifdef HTTP_DEBUG else xSerialPrintf_P(PSTR("HTTPD socket: %d, initialise success..!\r\n"),s); #endif if(pHTTPRequest == NULL) // if there is no buffer allocated (pointer is NULL), then allocate request buffer for all HTTP functions. { if( !(pHTTPRequest = (HTTP_REQUEST *) pvPortMalloc( sizeof(HTTP_REQUEST) ))) { xSerialPrint_P(PSTR("HTTP Request Buffer: malloc fail..!\r\n")); ret = 0; } #ifdef HTTP_DEBUG else xSerialPrint_P(PSTR("HTTP Request Buffer: malloc success..!\r\n")); #endif } if(pHTTPResponse == NULL) // if there is no buffer allocated (pointer is NULL), then allocate response buffer for all HTTP functions. { if( !(pHTTPResponse = (uint8_t *) pvPortMalloc( sizeof(uint8_t) * (FILE_BUFFER_SIZE + 1) ))) { xSerialPrint_P(PSTR("HTTP Response Buffer: malloc fail..!\r\n")); vPortFree(pHTTPRequest); ret = 0; } #ifdef HTTP_DEBUG else xSerialPrint_P(PSTR("HTTP Response Buffer: malloc success..!\r\n")); #endif } HTTPD_SOCK = s; return ret; }
/** * Writes an HID message with payload to the HID device using the interrupt endpoint * * @param device USB device handle. * @param data command payload. * @return error code or 0 for success. */ static int16_t hid_writeMessage( usb_device * device, uint8_t data ) { hid_bootKeyboardOutputReport message; int16_t rcode; // Fill out the message record. message.generic = data; if (*theConnection == HID_OPEN) { *theConnection = HID_WRITING; #ifdef DEBUG xSerialPrintf_P(PSTR("\r\nOUT << 0x%02x"), message.generic); #endif rcode = usb_bulkWrite(device, sizeof(hid_bootKeyboardOutputReport), (uint8_t*)&message); if (rcode < 0) return rcode; rcode = usb_bulkWrite(device, 1, (uint8_t *)&data); if (rcode < 0) return rcode; } *theConnection = HID_OPEN; return 0; }
/** * Helper function for usb_isHIDDevice to check whether an interface is a valid HID interface. * @param interface interface descriptor struct. */ static uint8_t usb_isHIDInterface(usb_interfaceDescriptor * interface) { // Check if the interface has exactly one endpoint (excluding the control endpoint 0). if (interface->bNumEndpoints!=1) return false; #ifdef DEBUG xSerialPrintf_P(PSTR("Interface class: %d\r\n"), interface->bInterfaceClass); xSerialPrintf_P(PSTR("Interface subclass: %d\r\n"), interface->bInterfaceSubClass); xSerialPrintf_P(PSTR("Interface protocol: %d\r\n"), interface->bInterfaceProtocol); #endif // Check if the endpoint supports interrupt transfer. if (interface->bInterfaceClass != HID_INTF) return false; if (interface->bInterfaceSubClass != BOOT_INTF_SUBCLASS) return false; if ( !(interface->bInterfaceProtocol && (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) ) return false; return true; }
/** * Print USB device information. */ int usb_printDeviceInfo(usb_device * device) { int rcode; // char buf[128]; // Read the device descriptor usb_deviceDescriptor deviceDescriptor; rcode = usb_getDeviceDescriptor(device, &deviceDescriptor); if (rcode) return rcode; xSerialPrintf_P(PSTR("\r\nVendor ID: %x\r\n"), deviceDescriptor.idVendor); xSerialPrintf_P(PSTR("Product ID: %x\r\n"), deviceDescriptor.idProduct); xSerialPrintf_P(PSTR("Configuration count: %d\r\n"), deviceDescriptor.bNumConfigurations); xSerialPrintf_P(PSTR("Device class: %d\r\n"), deviceDescriptor.bDeviceClass); xSerialPrintf_P(PSTR("Device subclass: %d\r\n"), deviceDescriptor.bDeviceSubClass); xSerialPrintf_P(PSTR("Device protocol: %d\r\n"), deviceDescriptor.bDeviceProtocol); /* usb_getString(device, deviceDescriptor.iManufacturer, device->firstStringLanguage, 128, buf); avr_serialPrintf("Manufacturer: %d %s\n", deviceDescriptor.iManufacturer, buf); usb_getString(device, deviceDescriptor.iProduct, device->firstStringLanguage, 128, buf); avr_serialPrintf("Product: %s\n", buf); usb_getString(device, deviceDescriptor.iSerialNumber, device->firstStringLanguage, 128, buf); avr_serialPrintf("Serial number: %s\n", buf); */ return 0; }
uint8_t* get_http_uri_name(uint8_t* uri) { uint8_t tempURI[MAX_URI_SIZE]; uint8_t* uri_name; if(!uri) return 0; strncpy((char *)tempURI, (const char *)uri, MAX_URI_SIZE); uri_name = (uint8_t*)strtok((char *)tempURI, " ?"); if(strcmp( (const char *)uri_name, "/" )) uri_name++; #ifdef HTTP_DEBUG xSerialPrintf_P(PSTR("\nuri_name=%s "),uri_name); #endif return (uint8_t*)uri_name; }
void hid_put_dump(const uint8_t *buffer, uint16_t cnt) { uint8_t i; for(i = 0; i < cnt; ++i) xSerialPrintf_P(PSTR(" %02X"), buffer[i]); xSerialPutChar( &xSerialPort, ' ' ); for(i = 0; i < cnt; ++i) { xSerialPutChar( &xSerialPort, (buffer[i] >= ' ' && buffer[i] <= '~') ? buffer[i] : '.' ); } xSerialPrint((uint8_t *)"\r\n"); vTaskDelay( 8 / portTICK_PERIOD_MS ); // Whoa... too fast. }
unsigned short fill_buf(void* blk) { uint16_t webpage_len; char int_string[4]; webpage_len = (strlen_P(webpage)>uip_mss())?uip_mss():strlen_P(webpage); xSerialPrintf_P(PSTR("fill_buf : %s\r\n"), webpage); memcpy_P(uip_appdata, webpage, webpage_len); sprintf(int_string, "%X", mfg_id[0]); memcpy(&uip_appdata[104], int_string, 2); sprintf(int_string, "%X", mfg_id[1]); memcpy(&uip_appdata[108], int_string, 2); return webpage_len; }
/** @brief Display result of ping */ void DisplayPingStatistics( PING_LOG log /**< result of ping */ ) { xSerialPrintf_P(PSTR("\r\n\tPackets: Sent = %d, Received = %d, Lost = %d\r\n"), log.PingRequest,log.PingReply+log.CheckSumErr+log.UnknownMSG+log.UnreachableMSG+log.TimeExceedMSG,log.Loss+log.ARPErr); if(log.CheckSumErr > 0) xSerialPrintf_P(PSTR("\tChecksum Error packets = %d\r\n"),log.CheckSumErr); if(log.UnreachableMSG > 0) xSerialPrintf_P(PSTR("\tUnreachable Message packets = %d\r\n"),log.UnreachableMSG); if(log.TimeExceedMSG > 0) xSerialPrintf_P(PSTR("\tTime Exceeded Message packets = %d\r\n"),log.TimeExceedMSG); if(log.UnknownMSG > 0) xSerialPrintf_P(PSTR("\tUnknown Message packets = %d\r\n"),log.UnknownMSG); if(log.ARPErr > 0) xSerialPrintf_P(PSTR("\tFail To Send ARP packets = %d\r\n"),log.ARPErr); if(log.Loss > 0) xSerialPrintf_P(PSTR("\tRequest timed out = %d\r\n"),log.Loss); if(log.PingReply > 0) xSerialPrintf_P(PSTR("\tPing Reply packets = %d\r\n"),log.PingReply); }
/** @brief get next parameter value in the request */ uint8_t* get_http_param_value( uint8_t* uri, uint8_t* param_name ) { uint8_t tempURI[MAX_URI_SIZE]; uint8_t* name=0; if(!uri || !param_name) return 0; strncpy((char *)tempURI, (const char *)uri, MAX_URI_SIZE); if((name=(uint8_t*)strstr((const char *)tempURI, (const char *)param_name))) { name += strlen((const char *)param_name) + 1; // strlen(para_name) + strlen("=") if((name = (uint8_t*)strtok((char *)name,"& \r\n\t\0"))) { unescape_http_url((uint8_t*)name); replacetochar((uint8_t*)name,'+',' '); } } #ifdef HTTP_DEBUG xSerialPrintf_P(PSTR("\n%s=%s "),param_name,name); #endif return (uint8_t*)name; }
/** @brief Send ping-request to the specified peer and receive ping-reply from the specified peer. @return 1 - success, 0 - fail because free socket is not found or can't be opened. */ uint8_t ping( uint8_t count, /**< Ping request count. */ uint16_t time, /**< wait ping reply time (unit : ms) */ uint8_t* addr, /**< Peer IP Address string in dotted decimal format */ PING_LOG* log /**< result of ping */ ) { PING_MSG* pPingRequest; // pointer for Ping Request PING_MSG* pPingReply; // pointer for Ping Reply uint32_t peerip; // 32 bit Peer IP Address uint32_t tempip; // IP address received from a destination uint16_t port; // port number received from a destination SOCKET s; // socket variable for pinging uint16_t RandomSeqNum; // Ping-Request ID uint16_t len; uint8_t IsReceived; // Received packet = 1, not received packet = 0 portTickType xInitialTick; /* Initialise PingRequest */ if( !(pPingRequest = (PING_MSG *) pvPortMalloc( sizeof(PING_MSG) ))) return 0; if( !(pPingReply = (PING_MSG *) pvPortMalloc( sizeof(PING_MSG) ))) { vPortFree(pPingRequest); return 0; } RandomSeqNum = htons( (uint16_t)rand()); // set ping-request's sequence number to random integer value pPingRequest->type = 0x08; // Ping-Request - ICMP pPingRequest->code = 0x00; // always 0 pPingRequest->checksum = 0; // value of checksum before calculating checksum of ping-request packet pPingRequest->id = htons(PING_ID); // set ping-request ID for(uint16_t i = 0 ; i < PING_OPT_LEN; i++) pPingRequest->OPT[i] = 'a' + i % 23; // fill 'a'~'w' characters into ping-request's data /* Initialise result of ping */ memset((void*)log,0,sizeof(PING_LOG)); /* Verify arguments */ if(!count) count = 4; // set count to default value (4 pings) if(!time) time = 1000; // set response time to default value (1000ms) /* Create a ping socket */ s = getSocket(SOCK_CLOSED,0); if(s == MAX_SOCK_NUM) // if it isn't exist free socket, Error { vPortFree(pPingRequest); vPortFree(pPingReply); return 0; } setSn_PROTO(s,IP_PROTO_ICMP); // Set upper-protocol of IP protocol if( socket( s, Sn_MR_IPRAW, 3000, 0) == 0) // Open IP_RAW Mode , if fail then Error { vPortFree(pPingRequest); vPortFree(pPingReply); return 0; } peerip = htonl( inet_addr(addr)); // convert address string into 32bit address xSerialPrintf_P(PSTR("\r\nPinging %s with %d bytes of data:\r\n"), addr, (sizeof(PING_MSG) - 8)); /* Ping Service */ while( count-- != 0) { IsReceived = 0; pPingRequest->seqNum = htons( RandomSeqNum++); // Increase Sequence number for next ping-request packet pPingRequest->checksum = 0; pPingRequest->checksum = htons( checksum( (uint8_t*)pPingRequest, sizeof(PING_MSG))); // update checksum field (*log).PingRequest++; // Increase PingRequest's value xInitialTick = xTaskGetTickCount(); if( sendto( s, (const uint8_t *)pPingRequest, sizeof(PING_MSG), (uint8_t*)&peerip, 3000)== 0) // Send Ping-Request to the specified peer. If fail, then it is occurred ARP Error. { (*log).ARPErr++; // Increase ARPErr close(s); // close the pinging socket /* Reopen pinging socket */ setSn_PROTO(s,IP_PROTO_ICMP); if(socket( s, Sn_MR_IPRAW, 3000, 0)==0) { vPortFree(pPingRequest); vPortFree(pPingReply); return 0; } continue; } while( xTaskGetTickCount() < (xInitialTick + ( time / portTICK_RATE_MS )) ) // as long as time is remaining { if((len = getSn_RX_RSR(s)) > 0) // Has pinging socket received a packet? { len = recvfrom( s, (uint8_t*)pPingReply, len, (uint8_t*)&tempip, &port); // receive a packet from unknown peer xSerialPrintf_P(PSTR("\r\nReply from %s"), inet_ntoa( ntohl(tempip))); // convert 32 bit unknown peer IP address into string of IP Address. if( checksum((uint8_t*)pPingReply,len) != 0) // if the packet's checksum value is correct { // not correct (*log).CheckSumErr++; // checksum error if(tempip == peerip) IsReceived = 1; xSerialPrint_P(PSTR(": Checksum Error")); } else if(pPingReply->type == 0) // if the received packet is ping-reply { if((pPingReply->id!=pPingRequest->id) || (pPingReply->seqNum!=pPingRequest->seqNum) || (tempip!=peerip)) // verify id,sequence nubmer, and ip address { xSerialPrint_P(PSTR(": Unmatched ID / SeqNum from peer")); // fail to verify (*log).UnknownMSG++; } else // success { IsReceived = 1; xSerialPrintf_P(PSTR(": bytes=%d, time<=%dms"),len-8,(xTaskGetTickCount()-xInitialTick)*portTICK_RATE_MS ); (*log).PingReply++; } } else if( pPingReply->type == 3) // If the packet is unreachable message { IsReceived = 1; xSerialPrint_P(PSTR(": Destination unreachable")); (*log).UnreachableMSG++; } else if( pPingReply->type == 11) // If the packet is time exceeded message { IsReceived = 1; xSerialPrint_P(PSTR(": TTL expired in transit")); (*log).TimeExceedMSG++; } else if( pPingReply->type == 8) // Send ping reply to a peer { xSerialPrint_P(PSTR(": Ping Request message")); SendPingReply(pPingReply,tempip); } else // if the packet is unknown message { xSerialPrintf_P(PSTR(": Unknown message (type = 0x%02X)"), pPingReply->type); (*log).UnknownMSG++; } } else if(getSn_SR(s)==SOCK_CLOSED) // if it is occurred to fail to send arp packet { (*log).ARPErr++; close(s); // close the pinging socket setSn_PROTO( s, IP_PROTO_ICMP); // reopen the pinging socket if(socket( s, Sn_MR_IPRAW, 3000, 0) == 0 ) { vPortFree(pPingRequest); vPortFree(pPingReply); return 0; } break; } if((xTaskGetTickCount() >= (xInitialTick + ( time / portTICK_RATE_MS ))) && (IsReceived == 0)) // If it is not received packet from the specified peer during waiting ping-reply packet. { (*log).Loss++; xSerialPrint_P(PSTR("Request timed out\r\n")); } } } /* Release pinging socket */ setSn_PROTO(s,0); close(s); vPortFree(pPingRequest); vPortFree(pPingReply); return 1; }
/** * Checks whether the a connected USB device is an HID device and populates a configuration record if it is. * * @param device USB device. * @param protocol desired protocol for endpoint (keyboard or mouse). * @param handle pointer to a configuration record. The endpoint device address, protocol (keyboard or mouse), and endpoint information will be stored here. * @return true if the device is an HID device. Assume Configuration 0 exactly 1 configuration is allowed. */ static uint8_t hid_isHIDDevice(usb_device * device, uint8_t protocol, hid_usbConfiguration * handle) { uint8_t ret = false; uint8_t buf[MAX_BUF_SIZE]; int16_t bytesRead; // Read the length of the configuration descriptor. bytesRead = usb_getConfigurationDescriptor(device, 0, MAX_BUF_SIZE, buf); if (bytesRead<0) return false; uint16_t pos = 0; uint8_t descriptorLength; uint8_t descriptorType; usb_configurationDescriptor * config = NULL; usb_interfaceDescriptor * interface = NULL; usb_endpointDescriptor * endpoint = NULL; while (pos < bytesRead) { descriptorLength = buf[pos]; descriptorType = buf[pos + 1]; switch (descriptorType) { case (USB_DESCRIPTOR_CONFIGURATION): config = (usb_configurationDescriptor *)(buf + pos); break; case (USB_DESCRIPTOR_INTERFACE): interface = (usb_interfaceDescriptor *)(buf + pos); if ( usb_isHIDInterface(interface) && (interface->bInterfaceProtocol == protocol)) { handle->configuration = config->bConfigurationValue; handle->interface = interface->bInterfaceNumber; // Detected requested HID interface! ret = true; #ifdef DEBUG xSerialPrintf_P(PSTR("HID Interface Descriptor parsed. 0x%02X\r\n"), interface->bInterfaceProtocol); #endif } break; case (USB_DESCRIPTOR_ENDPOINT): endpoint = (usb_endpointDescriptor *)(buf + pos); // If this endpoint descriptor is found right after the HID interface descriptor, it belongs to that interface. if (interface->bInterfaceNumber == handle->interface) { if (endpoint->bEndpointAddress & 0x80) { handle->inputEndPointAddress = endpoint->bEndpointAddress & ~0x80; #ifdef DEBUG xSerialPrintf_P(PSTR("HID INPUT Endpoint Descriptor parsed. 0x%02X\r\n"), handle->inputEndPointAddress); #endif }else{ handle->outputEndPointAddress = endpoint->bEndpointAddress; #ifdef DEBUG xSerialPrintf_P(PSTR("HID OUTPUT Endpoint Descriptor parsed. 0x%02X\r\n"), handle->outputEndPointAddress); #endif } } break; default: break; } pos += descriptorLength; } return ret; }
/** * Sends a control request to a USB device. * * @param device USB device to send the control request to. * @param requestType request type (in/out). * @param request request. * @param valueLow low byte of the value parameter. * @param valueHigh high byte of the value parameter. * @param index index. * @param length number of bytes to transfer. * @param data data to send in case of output transfer, or reception buffer in case of input. If no data is to be exchanged this should be set to NULL. * @return 0 on success, error code otherwise */ int usb_controlRequest( usb_device * device, uint8_t requestType, uint8_t request, uint8_t valueLow, uint8_t valueHigh, uint16_t index, uint16_t length, uint8_t * data) { boolean direction = false; //request direction, IN or OUT uint8_t rcode; usb_setupPacket setup_pkt; // Set device address. max3421e_write(MAX_REG_PERADDR, device->address); if (requestType & 0x80) direction = true; //determine request direction // Build setup packet. setup_pkt.bmRequestType = requestType; setup_pkt.bRequest = request; setup_pkt.wValue = valueLow | (valueHigh << 8); setup_pkt.wIndex = index; setup_pkt.wLength = length; // Write setup packet to the FIFO and dispatch max3421e_writeMultiple(MAX_REG_SUDFIFO, 8, (uint8_t *) &setup_pkt); rcode = usb_dispatchPacket(tokSETUP, &(device->control), USB_NAK_LIMIT); // Print error in case of failure. if (rcode) { xSerialPrintf_P(PSTR("Setup packet error: 0x%02x @ Tick: %u\r\n"), rcode, xTaskGetTickCount()); return -1; } // Data stage, if present if (data != NULL) { rcode = usb_ctrlData(device, direction, length, data); // If unsuccessful, return error. if (rcode<0) { xSerialPrintf_P(PSTR("\r\nData packet error: 0x%02x @ Tick: %u\r\n"), rcode, xTaskGetTickCount()); return -2; } } // Status stage. if (direction) rcode = usb_dispatchPacket(tokOUTHS, &(device->control), USB_NAK_LIMIT); else rcode = usb_dispatchPacket(tokINHS, &(device->control), USB_NAK_LIMIT); if (rcode) return -3; else return 0; }
/** * Performs an in transfer from a USB device from an arbitrary endpoint. * * @param device USB bulk device. * @param device length number of bytes to read. * @param data target buffer. * @return number of bytes read, or error code in case of failure. */ int usb_read(usb_device * device, usb_endpoint * endpoint, uint16_t length, uint8_t * data, unsigned int nakLimit) { uint16_t rcode, bytesRead; uint16_t maxPacketSize = endpoint->maxPacketSize; unsigned int totalTransferred = 0; // Set device address. max3421e_write(MAX_REG_PERADDR, device->address); // Set toggle value. max3421e_write(MAX_REG_HCTL, endpoint->receiveToggle); while (1) { // Start IN transfer rcode = usb_dispatchPacket(tokIN, endpoint, nakLimit); if (rcode) { if (rcode != hrNAK) xSerialPrintf_P(PSTR("usb_read: dispatch error %d @ Tick: %u\r\n"), rcode, xTaskGetTickCount()); return -1; } // Assert that the RCVDAVIRQ bit in register MAX_REG_HIRQ is set. if ((max3421e_read(MAX_REG_HIRQ) & bmRCVDAVIRQ) == 0) { xSerialPrintf_P(PSTR("usb_read: toggle error? %d @ Tick: %u\r\n"), rcode, xTaskGetTickCount()); // TODO: the absence of RCVDAVIRQ indicates a toggle error. Need to add handling for that. return -2; } // Obtain the number of bytes in FIFO. bytesRead = max3421e_read(MAX_REG_RCVBC); // Read the data from the FIFO. data = max3421e_readMultiple(MAX_REG_RCVFIFO, bytesRead, data); // Clear the interrupt to free the buffer. max3421e_write(MAX_REG_HIRQ, bmRCVDAVIRQ); totalTransferred += bytesRead; // Check if we're done reading. Either we've received a 'short' packet (<maxPacketSize), or the // desired number of bytes has been transferred. if ((bytesRead < maxPacketSize) || (totalTransferred >= length)) { // Remember the toggle value for the next transfer. if (max3421e_read(MAX_REG_HRSL) & bmRCVTOGRD) endpoint->receiveToggle = bmRCVTOG1; else endpoint->receiveToggle = bmRCVTOG0; // Break out of the loop. break; } } // Report success. return totalTransferred; }
static void TaskMonitor(void *pvParameters) // Monitor for Serial Interface { (void) pvParameters; uint8_t *ptr; int32_t p1; // create the buffer on the heap (so they can be moved later). if(LineBuffer == NULL) // if there is no Line buffer allocated (pointer is NULL), then allocate buffer. if( !(LineBuffer = (uint8_t *) pvPortMalloc( sizeof(uint8_t) * LINE_SIZE ))) xSerialPrint_P(PSTR("pvPortMalloc for *LineBuffer fail..!\r\n")); while(1) { xSerialPutChar(&xSerialPort, '>'); ptr = LineBuffer; get_line(ptr, (uint8_t)(sizeof(uint8_t)* LINE_SIZE)); //sizeof (Line); switch (*ptr++) { case 'h' : // help xSerialPrint_P( PSTR("rt - reset maximum & minimum temperatures\r\n") ); xSerialPrint_P( PSTR("t - show the time\r\n") ); xSerialPrint_P( PSTR("t - set the time\r\nt [<year yy> <month mm> <date dd> <day: Sun=0> <hour hh> <minute mm> <second ss>]\r\n") ); break; #ifdef portRTC_DEFINED case 't' : /* t [<year yy> <month mm> <date dd> <day: Sun=0> <hour hh> <minute mm> <second ss>] */ if (xatoi(&ptr, &p1)) { SetTimeDate.tm_year = (uint8_t)p1 + 100; // convert to (Gregorian - 1900) xatoi(&ptr, &p1); SetTimeDate.tm_mon = (uint8_t)p1; xatoi(&ptr, &p1); SetTimeDate.tm_mday = (uint8_t)p1; xatoi(&ptr, &p1); SetTimeDate.tm_wday = (uint8_t)p1; xatoi(&ptr, &p1); SetTimeDate.tm_hour = (uint8_t)p1; xatoi(&ptr, &p1); SetTimeDate.tm_min = (uint8_t)p1; if (!xatoi(&ptr, &p1)) break; SetTimeDate.tm_sec = (uint8_t)p1; xSerialPrintf_P(PSTR("Set: %u/%u/%u %2u:%02u:%02u\r\n"), SetTimeDate.tm_year, SetTimeDate.tm_mon, SetTimeDate.tm_mday, SetTimeDate.tm_hour, SetTimeDate.tm_min, SetTimeDate.tm_sec); if (setDateTimeDS1307( &SetTimeDate ) == pdTRUE) xSerialPrint_P( PSTR("Setting successful\r\n") ); } else { if (getDateTimeDS1307( &xCurrentTempTime.DateTime) == pdTRUE) xSerialPrintf_P(PSTR("Current: %u/%u/%u %2u:%02u:%02u\r\n"), xCurrentTempTime.DateTime.tm_year + 1900, xCurrentTempTime.DateTime.tm_mon, xCurrentTempTime.DateTime.tm_mday, xCurrentTempTime.DateTime.tm_hour, xCurrentTempTime.DateTime.tm_min, xCurrentTempTime.DateTime.tm_sec); } break; #endif case 'r' : // reset switch (*ptr++) { case 't' : // temperature xMaximumTempTime = xCurrentTempTime; xMinimumTempTime = xCurrentTempTime; // Now we commit the time and temperature to the EEPROM, forever... eeprom_update_block(&xMaximumTempTime, &xMaximumEverTempTime, sizeof(xRTCTempArray)); eeprom_update_block(&xMinimumTempTime, &xMinimumEverTempTime, sizeof(xRTCTempArray)); break; default : break; } break; default : break; } // xSerialPrintf_P(PSTR("\r\nSerial Monitor: Stack HighWater @ %u"), uxTaskGetStackHighWaterMark(NULL)); // xSerialPrintf_P(PSTR("\r\nFree Heap Size: %u\r\n"), xPortGetMinimumEverFreeHeapSize() ); // needs heap_1, heap_2 or heap_4 for this function to succeed. } }
//void main(int argc, char ** argv) { void TaskKermit(void *pvParameters) // Operate the Kermit Server { (void) pvParameters; int status, rx_len, i, x; char c; UCHAR *inbuf; short r_slot; parity = P_PARITY; /* Set this to desired parity */ status = X_OK; /* Initial kermit status */ xargc = argc; xargv = argv; xname = argv[0]; while (--xargc > 0) { /* Loop through command-line words */ xargv++; if (**xargv == '-') { /* Have dash */ c = *(*xargv+1); /* Get the option letter */ x = doarg(c); /* Go handle the option */ if (x < 0) doexit(FAILURE); } else { /* No dash where expected */ fatal("Malformed command-line option: '",*xargv,"'"); } } if (!action) /* Nothing to do, give usage message */ usage(); #ifdef DEBUG debug(DB_LOG,"SIMULATED ERROR RATE:",0,errorrate); if (errorrate) srand(seed); /* Init random error generator */ #endif /* DEBUG */ /* THE REAL STUFF IS FROM HERE DOWN */ xSerialPrintf_P(PSTR("\r\nFree Heap Size: %u"),xPortGetMinimumEverFreeHeapSize() ); // needs heap_1.c, heap_2.c or heap_4.c xSerialPrintf_P(PSTR("\r\nKermit HighWater: %u\r\n"), uxTaskGetStackHighWaterMark(NULL)); spiBegin(SDCard); // initialise the SPI bus for Kermit Server SD Card use. spiSelect (SDCard); if (!devopen("dummy")) /* Open the communication device */ doexit(FAILURE); if (!devsettings("dummy")) /* Perform any needed settings */ doexit(FAILURE); if (db) /* Open debug log if requested */ debug(DB_OPN,"debug.log",0,0); debug(DB_MSG,"Initializing...",0,0); /* Fill in parameters for this run */ k.xfermode = xmode; /* Text/binary automatic/manual */ k.remote = remote; /* Remote vs local */ k.binary = ftype; /* 0 = text, 1 = binary */ k.parity = parity; /* Communications parity */ k.bct = (check == 5) ? 3 : check; /* Block check type */ k.ikeep = keep; /* Keep incompletely received files */ k.filelist = cmlist; /* List of files to send (if any) */ k.cancel = 0; /* Not cancelled yet */ /* Fill in the i/o pointers */ k.zinbuf = i_buf; /* File input buffer */ k.zinlen = IBUFLEN; /* File input buffer length */ k.zincnt = 0; /* File input buffer position */ k.obuf = o_buf; /* File output buffer */ k.obuflen = OBUFLEN; /* File output buffer length */ k.obufpos = 0; /* File output buffer position */ /* Fill in function pointers */ k.rxd = readpkt; /* for reading packets */ k.txd = tx_data; /* for sending packets */ k.ixd = inchk; /* for checking connection */ k.openf = openfile; /* for opening files */ k.finfo = fileinfo; /* for getting file info */ k.readf = readfile; /* for reading files */ k.writef = writefile; /* for writing to output file */ k.closef = closefile; /* for closing files */ #ifdef DEBUG k.dbf = db ? dodebug : 0; /* for debugging */ #else k.dbf = 0; #endif /* DEBUG */ /* Force Type 3 Block Check (16-bit CRC) on all packets, or not */ k.bctf = (check == 5) ? 1 : 0; /* Initialize Kermit protocol */ status = kermit(K_INIT, &k, 0, 0, "", &r); #ifdef DEBUG debug(DB_LOG,"init status:",0,status); debug(DB_LOG,"version:",k.version,0); #endif /* DEBUG */ if (status == X_ERROR) doexit(FAILURE); if (action == A_SEND) status = kermit(K_SEND, &k, 0, 0, "", &r); /* Now we read a packet ourselves and call Kermit with it. Normally, Kermit would read its own packets, but in the embedded context, the device must be free to do other things while waiting for a packet to arrive. So the real control program might dispatch to other types of tasks, of which Kermit is only one. But in order to read a packet into Kermit's internal buffer, we have to ask for a buffer address and slot number. To interrupt a transfer in progress, set k.cancel to I_FILE to interrupt only the current file, or to I_GROUP to cancel the current file and all remaining files. To cancel the whole operation in such a way that the both Kermits return an error status, call Kermit with K_ERROR. */ while (status != X_DONE) { /* Here we block waiting for a packet to come in (unless readpkt times out). Another possibility would be to call inchk() to see if any bytes are waiting to be read, and if not, go do something else for a while, then come back here and check again. */ inbuf = getrslot(&k,&r_slot); /* Allocate a window slot */ rx_len = k.rxd(&k,inbuf,P_PKTLEN); /* Try to read a packet */ debug(DB_PKT,"main packet",&(k.ipktbuf[0][r_slot]),rx_len); /* For simplicity, kermit() ACKs the packet immediately after verifying it was received correctly. If, afterwards, the control program fails to handle the data correctly (e.g. can't open file, can't write data, can't close file), then it tells Kermit to send an Error packet next time through the loop. */ if (rx_len < 1) { /* No data was read */ freerslot(&k,r_slot); /* So free the window slot */ if (rx_len < 0) /* If there was a fatal error */ doexit(FAILURE); /* give up */ /* This would be another place to dispatch to another task */ /* while waiting for a Kermit packet to show up. */ } /* Handle the input */ switch (status = kermit(K_RUN, &k, r_slot, rx_len, "", &r)) { case X_OK: #ifdef DEBUG /* This shows how, after each packet, you get the protocol state, file name, date, size, and bytes transferred so far. These can be used in a file-transfer progress display, log, etc. */ debug(DB_LOG,"NAME",r.filename ? (char *)r.filename : "(NULL)",0); debug(DB_LOG,"DATE",r.filedate ? (char *)r.filedate : "(NULL)",0); debug(DB_LOG,"SIZE",0,r.filesize); debug(DB_LOG,"STATE",0,r.status); debug(DB_LOG,"SOFAR",0,r.sofar); #endif /* DEBUG */ /* Maybe do other brief tasks here... */ continue; /* Keep looping */ case X_DONE: break; /* Finished */ case X_ERROR: doexit(FAILURE); /* Failed */ break; } } doexit(SUCCESS); }
/** @brief parse http request from a peer */ void parse_http_request( HTTP_REQUEST *request, /**< request to be returned */ uint8_t *buffer /**< pointer to be parsed */ ) { uint8_t *nexttok; nexttok = (uint8_t *)strtok((char *)buffer," "); if(!nexttok) { request->METHOD = METHOD_ERR; return; } if (!strcmp_P((const char *)nexttok, PSTR("GET")) || !strcmp_P((const char *)nexttok, PSTR("get"))) { request->METHOD = METHOD_GET; nexttok = (uint8_t *)strtok(NULL," "); #ifdef HTTP_DEBUG xSerialPrint_P(PSTR("METHOD_GET ")); #endif } else if (!strcmp_P((const char *)nexttok, PSTR("HEAD")) || !strcmp_P((const char *)nexttok, PSTR("head"))) { request->METHOD = METHOD_HEAD; nexttok = (uint8_t *)strtok(NULL," "); #ifdef HTTP_DEBUG xSerialPrint_P(PSTR("METHOD_HEAD ")); #endif } else if (!strcmp_P((const char *)nexttok, PSTR("POST")) || !strcmp_P((const char *)nexttok, PSTR("post"))) { nexttok = (uint8_t *)strtok((char *)NULL,"\0"); request->METHOD = METHOD_POST; #ifdef HTTP_DEBUG xSerialPrint_P(PSTR("METHOD_POST ")); #endif } else { request->METHOD = METHOD_ERR; #ifdef HTTP_DEBUG xSerialPrint_P(PSTR("METHOD_ERR ")); #endif } if(!nexttok) { request->METHOD = METHOD_ERR; #ifdef HTTP_DEBUG xSerialPrint_P(PSTR("METHOD_ERR ")); #endif return; } strcpy((char *)request->URI,(const char *)nexttok); #ifdef HTTP_DEBUG { uint16_t i; xSerialPrint_P(PSTR("\nhttp_request->URI: ")); for(i=0; i < strlen((const char *)request->URI);i++) xSerialPrintf_P(PSTR("%c"),request->URI[i]); xSerialPrint_P(PSTR("")); } #endif }
/** @brief Analyse HTTP request and then services WEB. */ void process_HTTP( SOCKET s, /**< http server socket */ uint8_t * buffer, /**< buffer pointer included http request */ uint16_t length /**< length of http request */ ) { uint8_t * name; uint16_t bytes_read; TickType_t wait_send; FIL source_file; /* File object for the source file */ parse_HTTP_request(pHTTPRequest, buffer); // After analysing request, convert into pHTTPRequest /* method Analyse */ switch (pHTTPRequest->METHOD) { case METHOD_HEAD: case METHOD_GET : case METHOD_POST : name = get_HTTP_URI_name(pHTTPRequest->URI); if (!strcmp((const char *)name, "/")) strcpy((char *)name,"index.htm"); // If URI is "/", respond by index.htm #ifdef WEB_DEBUG if(strlen( (const char *)name) < MAX_INT_STR ) xSerialPrintf_P(PSTR("\r\nPAGE : %s "), name); else xSerialPrint_P(PSTR("\r\nFILENAME TOO LONG")); #endif find_HTTP_URI_type(&pHTTPRequest->TYPE, name); //Check file type (HTML, TEXT, ICO, GIF, JPEG, ZIP are included) // OK now we start to respond to the info we've decoded. /* Open the specified file stored in the SD card FAT32 */ if (f_open(&source_file, (const TCHAR *)name, FA_OPEN_EXISTING | FA_READ)) { // if file open failure memcpy_P( (char *)pHTTPResponse, ERROR_HTML_PAGE, strnlen_P(ERROR_HTML_PAGE, FILE_BUFFER_SIZE) ); #ifdef WEB_DEBUG xSerialPrint_P(PSTR("HTTP Unknown file or page.\r\n")); xSerialPrintf_P(PSTR("HTTP Response...\r\n%s\r\nResponse Size: %u \r\n"), pHTTPResponse, strlen_P(ERROR_HTML_PAGE)); #endif send( s, (const uint8_t*)pHTTPResponse, strlen_P(ERROR_HTML_PAGE)); } else { // if file open success make_HTTP_response_header( pHTTPResponse, pHTTPRequest->TYPE, source_file.fsize); #ifdef WEB_DEBUG xSerialPrintf_P(PSTR("HTTP Opened file: %s Source Size: %u \r\n"), name, source_file.fsize); xSerialPrintf_P(PSTR("HTTP Response Header...\r\n%s\r\nResponse Header Size: %u \r\n"), pHTTPResponse, strlen((char*)pHTTPResponse )); #endif send(s, (const uint8_t*)pHTTPResponse, strlen((char*)pHTTPResponse )); wait_send = xTaskGetTickCount(); while(getSn_TX_FSR(s)!= WIZCHIP_getTxMAX(s)) { if( (xTaskGetTickCount() - wait_send) > (WEBSERVER_SOCKET_TIMEOUT / portTICK_PERIOD_MS) ) // wait up to 1.5 Sec { #ifdef WEB_DEBUG xSerialPrint_P(PSTR("HTTP Response head send fail\r\n")); #endif break; } vTaskDelay( 0 ); // yield until next tick. } for (;;) { if ( f_read(&source_file, pHTTPResponse, (sizeof(uint8_t)*(FILE_BUFFER_SIZE) ), &bytes_read) || bytes_read == 0 ) break; // read error or reached end of file if(pHTTPRequest->TYPE == PTYPE_HTML) // if we've got a html document, there might be some system variables to set { *(pHTTPResponse + bytes_read + 1) = 0; // make the buffer a string, null terminated bytes_read = replace_sys_env_value(pHTTPResponse, bytes_read); // Replace html system environment value to real value } if (send(s, (const uint8_t*)pHTTPResponse, bytes_read) != bytes_read) break; // TCP/IP send error wait_send = xTaskGetTickCount(); while(getSn_TX_FSR(s)!= WIZCHIP_getTxMAX(s)) { if( (xTaskGetTickCount() - wait_send) > (WEBSERVER_SOCKET_TIMEOUT / portTICK_PERIOD_MS) ) // wait up to 1.5 Sec { #ifdef WEB_DEBUG xSerialPrint_P(PSTR("HTTP Response body send fail\r\n")); #endif break; } vTaskDelay( 0 ); // yield until next tick. } } f_close(&source_file); eeprom_busy_wait(); eeprom_update_dword( &pagesServed, eeprom_read_dword(&pagesServed) +1 ); } break; case METHOD_ERR : memcpy_P( (char *)pHTTPResponse, ERROR_REQUEST_PAGE, strnlen_P(ERROR_REQUEST_PAGE, FILE_BUFFER_SIZE) ); #ifdef WEB_DEBUG xSerialPrint_P(PSTR("HTTP Method Error.\r\n")); xSerialPrintf_P(PSTR("HTTP Response...\r\n%s\r\nResponse Size: %u \r\n"), pHTTPResponse, strlen_P(ERROR_REQUEST_PAGE)); #endif send( s, (const uint8_t*)pHTTPResponse, strlen_P(ERROR_REQUEST_PAGE)); break; default : break; } }