Exemplo n.º 1
0
void cdc_req_handler(req_t *req)
{
    U8 i;
    usb_pcb_t *pcb = usb_pcb_get();
    
    switch (req->req)
    {
    case GET_LINE_CODING:
        if (req->type & (DEVICE_TO_HOST | TYPE_CLASS | RECIPIENT_INTF))
        {
            // send the line coding to the host
            for (i=0; i<LINE_CODE_SZ; i++)
            {
                usb_buf_write(EP_CTRL, line_code[i]);
            }
            ep_write(EP_CTRL);
        }
        break;

    case SET_LINE_CODING:
        if (req->type & (HOST_TO_DEVICE | TYPE_CLASS | RECIPIENT_INTF))
        {
            // wait for the setup data to be sent to the control endpoint
            while (pcb->fifo[EP_CTRL].len == 0)
            {
                // keep the nop for a place to set a breakpoint on and to make it obvious we're
                // waiting for something.
                asm("nop");
            }

            // clear the setup flag if needed
            pcb->flags &= ~(1<<SETUP_DATA_AVAIL);

            // send out a zero-length packet to ack to the host that we received
            // the new line coding
            ep_send_zlp(EP_CTRL);

            // set the new line code. the first 8 bytes in the fifo are just
            // for the setup packet so we want to write the next 7 bytes for the
            // line code.
            for (i=0; i<LINE_CODE_SZ; i++)
            {
                line_code[i] = usb_buf_read(EP_CTRL);
            }
        }
        break;

    case SET_CTRL_LINE_STATE:
        if (req->type & (HOST_TO_DEVICE | TYPE_CLASS | RECIPIENT_INTF))
        {
            ep_send_zlp(EP_CTRL);
        }
        break;

    default:
        ep_set_stall(EP_CTRL);
        break;
    }
}
Exemplo n.º 2
0
/*
 * This is the putchar function that is used by avr-libc's printf. We need
 * to hook this function into the stdout file stream using the FDEV_SETUP_STREAM
 * macro in avr-libc. Once the stream is set up, we hook the stream to stdout
 * and we can do printfs via USB.
 */
int freakusb_putchar(char c, FILE *unused)
{
	usb_pcb_t *pcb = usb_pcb_get();

	if (!(pcb->flags & (1 << ENUMERATED)))
		return 0;

	if (c == '\n') {
		usb_buf_write(EP_1, '\n');
		usb_buf_write(EP_1, '\r');
	} else {
		usb_buf_write(EP_1, (U8)c);
	}

	ep_write(EP_1);
	return 0;
}
Exemplo n.º 3
0
void dfu_req_handler(req_t *req)
{
    U8 i;
    usb_pcb_t *pcb = usb_pcb_get();

    switch (req->req)
    {
    case DFU_DETACH:
        if (req->type & (HOST_TO_DEVICE | TYPE_CLASS | RECIPIENT_INTF))
        {
            // wvalue is wTimeout
            // wLength is zero
            // data is none
            dfu_status.bState = appDETACH;
            dfu_status.bStatus = OK;

        }
        break;

    case DFU_DNLOAD:
        if (req->type & (HOST_TO_DEVICE | TYPE_CLASS | RECIPIENT_INTF))
        {
            // wvalue is wBlockNum
            // wlength is Length
            // data is firmware
            if( dfu_status.bState == dfuIDLE )
            {
                if( req->len > 0 )
                {
                    hw_state_indicator( HW_STATE_TRANSFER );
                    dfu_status.bState = dfuDNLOAD_SYNC;
                }
                else
                {
                    dfu_status.bState  = dfuERROR;
                    dfu_status.bStatus = errNOTDONE;
                    hw_state_indicator( HW_STATE_ERROR );
                    ep_send_zlp(EP_CTRL);
                    return;
                }
            }
        	i = req->val;
            if( dfu_status.bState == dfuDNLOAD_IDLE )
            {
                if( req->len > 0 )
                {
                    dfu_status.bState = dfuDNLOAD_SYNC;
                }
                else
                {
                    if( flash_buffer_ptr > flash_buffer )
                    {
                        need_to_write = 1;
                        //flash_buffer_ptr = flash_buffer;
                    }
                    dfu_status.bState  = dfuMANIFEST_SYNC;
                    ep_send_zlp(EP_CTRL);
                    return;
                }
            }

            SI32_USB_A_clear_out_packet_ready_ep0(SI32_USB_0);

            while(pcb->fifo[EP_CTRL].len < req->len)
            {
                //ep_read(EP_CTRL);
            	i = pcb->fifo[EP_CTRL].len;
            }

            // clear the setup flag if needed
            pcb->flags &= ~(1<<SETUP_DATA_AVAIL);

            // send out a zero-length packet to ack to the host that we received
            // the new line coding
            U8* byte_buf_ptr = ( U8* )flash_buffer_ptr;
            U8 tmp_len = pcb->fifo[EP_CTRL].len;
            for(i = 0; i < tmp_len; i++)
            {
                *byte_buf_ptr = usb_buf_read(EP_CTRL);
                byte_buf_ptr++;
            }
            flash_buffer_ptr += i/4;

            if( flash_buffer_ptr == flash_buffer + BLOCK_SIZE_U32 )
            {
                // Reset buffer pointer
                //flash_buffer_ptr = flash_buffer;
                need_to_write = 1;
            }

            if( flash_buffer_ptr > flash_buffer + BLOCK_SIZE_U32)
            {
                dfu_status.bState  = dfuERROR;
                hw_state_indicator( HW_STATE_ERROR );
            }

            ep_send_zlp(EP_CTRL);
        }
        break;

    case DFU_UPLOAD:
        if (req->type & (DEVICE_TO_HOST | TYPE_CLASS | RECIPIENT_INTF))
        {
            // wvalue is zero
            // wlength is length
            // data is firmware
            // NOT SUPPORTED
            ep_set_stall(EP_CTRL);
        }
        break;

    case DFU_GETSTATUS:
        if (req->type & (DEVICE_TO_HOST | TYPE_CLASS | RECIPIENT_INTF))
        {
            if( dfu_communication_started == 0 )
                hw_state_indicator( HW_STATE_CONNECTED );

            dfu_communication_started = 1;
            // If we're still transmitting blocks
            if( dfu_status.bState == dfuDNLOAD_SYNC )
            {
                if( need_to_write == 0 )
                {
                    dfu_status.bState=dfuDNLOAD_IDLE;
                    dfu_status.bwPollTimeout0 = 0x00;
                }
                else
                {
                	dfu_status.bState=dfuDNBUSY;
                    dfu_status.bwPollTimeout0 = 0x3F;
                }
            }
            else if( dfu_status.bState == dfuDNBUSY )
            {
                if( need_to_write == 0)
                    dfu_status.bState=dfuDNLOAD_SYNC;
            }
            else if( dfu_status.bState == dfuMANIFEST_SYNC)
            {
            	dfu_status.bState=dfuMANIFEST;
                dfu_status.bwPollTimeout0 = 0xFF;
                hw_state_indicator( HW_STATE_DONE );
            }
            else if( dfu_status.bState == dfuMANIFEST &&
                     need_to_write == 0)
            {
                // Finish erasing flash
                while( flash_target < SI32_MCU_FLASH_SIZE)
                {
                    if( 0 != hw_flash_erase( flash_target, 1 ) )
                    {
                        dfu_status.bState  = dfuERROR;
                        dfu_status.bStatus = errERASE;
                        hw_state_indicator( HW_STATE_ERROR );
                    }
                    flash_target += BLOCK_SIZE_U8;
                }
                dfu_status.bState=dfuMANIFEST_WAIT_RESET;
            }

            for (i=0; i<STATUS_SZ; i++)
            {
                usb_buf_write(EP_CTRL, *((U8 *)&dfu_status + i));
            }
            ep_write(EP_CTRL);

            if( dfu_status.bState == dfuMANIFEST_WAIT_RESET )
            {
                hw_wait_ms(200);
                hw_boot_image( 1 );
            }

            if( need_to_write )
            {
                if( 0 != hw_flash_erase( flash_target, 1 ) )
                {
                    dfu_status.bState  = dfuERROR;
                    dfu_status.bStatus = errERASE;
                    hw_state_indicator( HW_STATE_ERROR );
                }
                if( 0 != hw_flash_write( flash_target, ( U32* )flash_buffer, flash_buffer_ptr - flash_buffer, 1 ) )
                {
                    dfu_status.bState  = dfuERROR;
                    dfu_status.bStatus = errVERIFY;
                    hw_state_indicator( HW_STATE_ERROR );
                }
                flash_buffer_ptr = flash_buffer;
                flash_target += BLOCK_SIZE_U8;
                need_to_write = 0;
                if( dfu_status.bState != dfuMANIFEST )
                    dfu_status.bState=dfuDNLOAD_SYNC;
            }
        }
        break;

    case DFU_CLRSTATUS:
        if (req->type & (HOST_TO_DEVICE | TYPE_CLASS | RECIPIENT_INTF))
        {
            // wvalue is zero
            // wlength is 0
            // data is  none
            if( dfu_status.bState == dfuERROR )
            {
                dfu_status.bStatus = OK;
                dfu_status.bState = dfuIDLE;
                hw_state_indicator( HW_STATE_ERROR_CLR );
            }
        }
        break;

    case DFU_GETSTATE:
        if (req->type & (DEVICE_TO_HOST | TYPE_CLASS | RECIPIENT_INTF))
        {
            // wvalue is zero
            // wlength is 1
            // data is  state
            // Transition?: No State Transition
            usb_buf_write( EP_CTRL, dfu_status.bState );
            ep_write(EP_CTRL);
        }
        break;

    case DFU_ABORT:
        if (req->type & (HOST_TO_DEVICE | TYPE_CLASS | RECIPIENT_INTF))
        {
            // wvalue is zero
            // wlength is 0
            // data is none
            if( dfu_status.bState == dfuIDLE )
            {
                dfu_status.bStatus = OK;
                dfu_status.bState = dfuIDLE;
            }
            else if ( dfu_status.bState == dfuDNLOAD_IDLE )
            {
                flash_target = FLASH_TARGET;
                if( 0 != hw_flash_erase( flash_target, 1 ) )
                {
                    dfu_status.bState  = dfuERROR;
                    dfu_status.bStatus = errERASE;
                    hw_state_indicator( HW_STATE_ERROR );
                }
                dfu_status.bStatus = OK;
                dfu_status.bState = dfuIDLE;
                ep_send_zlp(EP_CTRL);
            }
        }
        break;

    default:
        ep_set_stall(EP_CTRL);
        break;
    }
}
Exemplo n.º 4
0
int main(int argc, char *argv[])
{
	int result;
	libusb_context *ctx;
	libusb_device_handle *usb_device;
	unsigned char *txbuf;
	int size;
	int retcode;
	int last_serial = -1;
	FILE *fp1, *fp2, *fp;

	char def1_inst[] = "/usr/share/rpiboot/usbbootcode.bin";
	char def2_inst[] = "/usr/share/rpiboot/msd.elf";
	char def3_inst[] = "/usr/share/rpiboot/buildroot.elf";

	char def1_loc[] = "./usbbootcode.bin";
	char def2_loc[] = "./msd.elf";
	char def3_loc[] = "./buildroot.elf";

	char *def1, *def2, *def3;

	char *stage1   = NULL, *stage2     = NULL;
	char *fatimage = NULL, *executable = NULL;
	int loop       = 0;

// if local file version exists use it else use installed
	if( access( def1_loc, F_OK ) != -1 ) { def1 = def1_loc; } else { def1 = def1_inst; }
	if( access( def2_loc, F_OK ) != -1 ) { def2 = def2_loc; } else { def2 = def2_inst; }
	if( access( def3_loc, F_OK ) != -1 ) { def3 = def3_loc; } else { def3 = def3_inst; }

	stage1   = def1;
	stage2   = def2;

	struct MESSAGE_S {
		int length;
		unsigned char signature[20];
	} message;
	
#if defined (__CYGWIN__)
  //printf("Running under Cygwin\n");
#else
	//exit if not run as sudo
	if(getuid() != 0)
	{
		printf("Must be run with sudo...\n");
		exit(-1);
	}
#endif

	// Skip the command name
	argv++; argc--;
	while(*argv)
	{
		if(strcmp(*argv, "-b") == 0)
		{
			argv++; argc--;
			if(argc < 1)
				usage(1);
			stage1 = def1;
			stage2 = def3;
			fatimage = *argv;
		}
		else if(strcmp(*argv, "-h") == 0 || strcmp(*argv, "--help") == 0)
		{
			usage(0);
		}
		else if(strcmp(*argv, "-x") == 0)
		{
			argv++; argc--;
			executable = *argv;
		}
		else if(strcmp(*argv, "-l") == 0)
		{
			loop = 1;
		}
		else if(strcmp(*argv, "-v") == 0)
		{
			verbose = 1;
		}
		else
		{
			usage(1);
		}
		
		argv++; argc--;
	}

	fp1 = fopen(stage1, "rb");
	if (fp1 == NULL)
	{
		printf("Cannot open file %s\n", stage1);
		exit(-1);
	}

	fp2 = fopen(stage2, "rb");
	if (fp2 == NULL)
	{
		printf("Cannot open file %s\n", stage2);
		exit(-1);
	}
	if(strcmp(stage2 + strlen(stage2) - 4, ".elf"))
	{
		printf("Third stage needs to be .elf format\n");
		exit(-1);
	}

	int ret = libusb_init(&ctx);
	if (ret)
	{
		printf("Failed to initialise libUSB\n");
		exit(-1);
	}

	libusb_set_debug(ctx, 0);

	do
	{
		FILE *fp_img = NULL;
		struct libusb_device_descriptor desc;

		printf("Waiting for BCM2835 ...\n");

		// Wait for a device to get plugged in
		do
		{
			result = Initialize_Device(&ctx, &usb_device);
			if(result == 0)
			{
				libusb_get_device_descriptor(libusb_get_device
								 (usb_device), &desc);
				// Make sure we've re-enumerated since the last time
				if(desc.iSerialNumber == last_serial)
				{
					result = -1;
					libusb_close(usb_device);
				}			
			}

			if (result)
			{
				usleep(100);
			}
		}
		while (result);

		last_serial = desc.iSerialNumber;
		printf("Found serial = %d: writing file %s\n",
		       desc.iSerialNumber,
		       desc.iSerialNumber == 0 ? stage1 : stage2);
		fp = desc.iSerialNumber == 0 ? fp1 : fp2;

		fseek(fp, 0, SEEK_END);
		message.length = ftell(fp);
		fseek(fp, 0, SEEK_SET);

		if(desc.iSerialNumber == 1 && fatimage != NULL)
		{
			// Been given a filesystem image
			fp_img = fopen(fatimage, "rb");
			if(fp_img == NULL)
			{
				printf("Failed to open image %s\n", fatimage);
				exit(-1);
			}
			fseek(fp_img, 0, SEEK_END);
			message.length += ftell(fp_img);
			if(verbose) printf("Adding %ld bytes of binary to end of elf\n", ftell(fp_img));
			fseek(fp_img, 0, SEEK_SET);
		}

		txbuf = (unsigned char *)malloc(message.length);
		if (txbuf == NULL)
		{
			printf("Failed to allocate memory\n");
			exit(-1);
		}

		size = fread(txbuf, 1, message.length, fp);
		if(fp_img)
		{
			size += fread(txbuf + size, 1, message.length - size, fp_img);
		}

		size =
		    ep_write((unsigned char *)&message, sizeof(message),
			     usb_device);
		if (size != sizeof(message))
		{
			printf("Failed to write correct length, returned %d\n",
			       size);
			exit(-1);
		}
		if(verbose) printf("Writing %d bytes\n", message.length);
		size = ep_write(txbuf, message.length, usb_device);
		if (size != message.length)
		{
			printf("Failed to read correct length, returned %d\n",
			       size);
			exit(-1);
		}

		size =
		    ep_read((unsigned char *)&retcode, sizeof(retcode),
			    usb_device);

		if (retcode == 0)
		{
			if(verbose) printf("Successful\n");

			if(fp == fp2 && executable)
			{
				system(executable);
			}
		}
		else
			printf("Failed : 0x%x", retcode);

		libusb_close(usb_device);
	}
	while(fp == fp1 || loop);

	libusb_exit(ctx);

	return 0;
}