📄 usbdrv.c
字号:
/* * USB Device Driver module *//* * CHANGELOG: * 02-sep-2003 created by Stanley.zhu<zhu.shan@zte.com.cn> *-------------------------------------------------------------------------*/#include "usbdrv.h"#include <ukey_proto.h>#include<config.h>//#define DEBUG 1#undef DEBUG#ifdef DEBUG#define DPRINTS(x) print_string(x)#define DPRINTL(x) print_long(x)#else#define DPRINTS(x)#define DPRINTL(x)#endifusb_devreq g_req;/*UDC_BUF_SIZE define in usbdrv.h */volatile unsigned char udc_data_buf[UDC_BUF_SIZE];/*usb device descriptor*/const usb_device_descriptor zteic_dev_desc={18,1,0x10,0x01,0xdc,0,0,8,0x11,0x11,0x22,0x22,0,0x01,0,0,0,1};/*usb configuration descriptors*/const unsigned char zteic_cfg_desc [32] = { //configuration desc 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x40, 0xf0, //interface desc 0x09, 0x04, 0x00, 0x00, 0x02, 0xdc, 0xa0, 0xb0, 0x00, //ep1 desc 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, //ep2 desc 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00 };/*get the num of endpoint INPUT: * in : ( 16 bits of) endpoint interrupt register value : high 16 bits --> out_ep_num low 16 bits --> in_ep_num OUTPUT: none; RETURN: in or out endpoint num; */void usb_fifo_out(unsigned char * buffer,unsigned pkt_sz, unsigned epnum);void usb_fifo_in( unsigned char *buffer, unsigned pkt_sz,unsigned ep_num);unsigned get_ep_num(unsigned in){ if (in == 1) return 0; else if (in == 2) return 1; else if (in == 4) return 2; else if (in == 8) return 3; else return UDC_MAX_ENDPT_NUM + 1;}/*get status register addr from endpoint number INPUT: * dir : direction (in or out); * ep_num: endpoint num; OUTPUT: none; RETURN: * address: status register addr; */ unsigned get_ep_sts_addr(unsigned dir, unsigned ep_num){ unsigned int address; if (dir == UDC_DIR_OUT) address = UDC_BASE_ADDR + ep_num * 0x20 + 0x204; else address = UDC_BASE_ADDR + ep_num * 0x20 + 0x04; return address;}/*get status of endpoint INPUT: * direction : direction (in or out); * ep_num: endpoint num; OUTPUT: none; RETURN: * status: endpoint status; */ unsigned get_ep_sts(unsigned direction, unsigned ep_num){ unsigned int address, status; address = get_ep_sts_addr(direction, ep_num); udc_get_reg(address, status); return status;}/*clear endpoint status register INPUT: * direction : direction (in or out); * ep_num: endpoint num; * mask : mask bits OUTPUT: none; RETURN: none; */ void clr_ep_sts(unsigned direction, unsigned ep_num, unsigned mask){ unsigned int address, status; address = get_ep_sts_addr (direction, ep_num); udc_get_reg (address, status); udc_set_reg (address, (status&(~mask))); return;}/* get length of packet INPUT: * ep_num: endpoint num; OUTPUT: none; RETURN: * pktsz: packet length; */ unsigned get_pkt_sz(unsigned ep_num){ unsigned status; status = get_ep_sts(UDC_DIR_OUT, ep_num); return ((status & 0x03ff800) >> 11);}/* when host setup the usb device, interrupt calls this function INPUT: * ep_num: endpoint num; OUTPUT: none; RETURN: none; */void usb_setup_handler(unsigned ep_num) { unsigned dev_type; unsigned tmp, len,i; unsigned command_type=0; /*get request length*/ if(g_req.request==0xb5) { ClearBootRomFlag(); return; } len = g_req.length_hi; len<<=8 ; len+= g_req.length_lo; usb_info.total_len = len; usb_info.cur_len = 0; /* get request */ usb_info.command = g_req.request; /* get request type*/ usb_info.type = g_req.value_hi; usb_info.count = 0; command_type = g_req.request; switch (command_type) { case GET_DESCRIPTOR: dev_type = g_req.value_hi; if(dev_type==0) {dev_type=2; usb_info.type = dev_type; } switch (dev_type) { case Device_Type: break; case Config_Type: if(usb_info.total_len > 32) usb_info.total_len=32; break; case String_Type: break; case Interface_Type: break; case Endpoint_Type: break; } break; case GET_CONFIGURATION: break; case GET_INTERFACE: break; case GET_STATUS: break; default: { break; } } }/*main handler of usb interrupt INPUT: none; OUTPUT: none; RETURN: none; */void usb_int_handler() { unsigned int device_intr_data; unsigned int ep_intr_data; unsigned int out_ep_num, in_ep_num; unsigned int status ,dev_ctrl; unsigned int pkt_sz ; int left_len=0; status = 0; udc_get_reg(UDC_DevIntr, device_intr_data); udc_get_reg(UDC_EPIntr, ep_intr_data); DPRINTS("enter usb int "); DPRINTL(device_intr_data); DPRINTL(ep_intr_data); /*device interrupt */ if (device_intr_data) { /*clear the register */ udc_set_reg(UDC_DevIntr, device_intr_data); } /*end point interrupt*/ if (ep_intr_data) { /*get the out endpoit num*/ out_ep_num = get_ep_num (ep_intr_data >> 16); /*get the in endpoit num*/ in_ep_num = get_ep_num (ep_intr_data & 0x0000ffff); DPRINTS("enter ep interrupt"); DPRINTL(out_ep_num); DPRINTL(in_ep_num); if (out_ep_num <= UDC_MAX_ENDPT_NUM) { if(out_ep_num>0) return; status = get_ep_sts(UDC_DIR_OUT, out_ep_num); //clear ep interrupt register udc_set_reg (UDC_EPIntr, ep_intr_data & 0xffff0000); DPRINTS("enter ep out"); } else if (in_ep_num <= UDC_MAX_ENDPT_NUM) { DPRINTS("enter ep in"); status = get_ep_sts(UDC_DIR_IN, in_ep_num); } if (status & UDC_EP_STS_IN) //in { //if ep0 in if(in_ep_num == 0 ) { switch(usb_info.command) { case GET_DESCRIPTOR: left_len = usb_info.total_len - usb_info.cur_len; switch (usb_info.type) { case Device_Type: /*send out device descriptor*/ if (left_len > 8) // 8 == max packet size usb_fifo_out((unsigned char *)(&zteic_dev_desc) + usb_info.cur_len,8,0); else usb_fifo_out((unsigned char *)(&zteic_dev_desc) + usb_info.cur_len, left_len, 0); usb_info.cur_len += 8; break; case Config_Type: /*send out configuration descriptors*/ if (left_len > 8) // 8 == max packet size usb_fifo_out((unsigned char *)(&zteic_cfg_desc) + usb_info.cur_len,8,0); else usb_fifo_out((unsigned char *)(&zteic_cfg_desc) + usb_info.cur_len, left_len, 0); usb_info.cur_len += 8; break; //else do nothing case String_Type: break; case Interface_Type: break; case Endpoint_Type: break; } break; //else do nothing default: break; } /*clear status register*/ clr_ep_sts(UDC_DIR_IN, in_ep_num, UDC_EP_STS_IN); //clear interrupt register udc_set_reg (UDC_EPIntr, ep_intr_data & 0x0ffff); } } if (status & UDC_EP_STS_OUT) { //if host error if (status & UDC_EP_STS_HE) { udc_get_reg(UDC_DevControl, dev_ctrl); /*software disconnect */ udc_set_reg (UDC_DevControl, dev_ctrl & 0x400); } // Recieve setup request if ((status & UDC_EP_STS_OUT) == UDC_EP_OUT_SETUP_DAT) { //clear ep out status clr_ep_sts(UDC_DIR_OUT, out_ep_num, UDC_EP_STS_OUT); //read out packet to g_req usb_fifo_in((unsigned char *)(&g_req),8,out_ep_num); //start setup handler usb_setup_handler(out_ep_num); } else // Receive normal data { //clear ep out status clr_ep_sts(UDC_DIR_OUT, out_ep_num, UDC_EP_STS_OUT); //get the out packet size pkt_sz = get_pkt_sz(out_ep_num); //read out packet to udc_data_buf usb_fifo_in((unsigned char *)udc_data_buf, pkt_sz,out_ep_num); } } } }void init_usb_info_struct(){ usb_info.command = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -