Linux
USB
aucd29
2013. 9. 26. 20:53
//
// Module Registration
//
int init_module(void)
{
int result;
result = register_chrdev(usb_major, "USB", &usb_fops);
if (result < 0) {
printk("USB can't get major \n");
return result;
}
else if (usb_major == 0) usb_major = result;
printk("USB Init, major number : %d\n", result);
return 0;
}
void cleanup_module(void)
{
unregister_chrdev(usb_major, "USB");
}
//
// usb_open();, usb_release();
//
static int usb_open(struct inode * inode, struct file * file)
{
if (usb_usage!=0)
return -EBUSY;
usbctl_create_descriptors();
usb_init();
MOD_INC_USE_COUNT;
usb_usage=1;
Ser0UDCCR = 0;
printk("USB opened\n");
return(0);
}
static int usb_release(struct inode * inode, struct file * file)
{
MOD_DEC_USE_COUNT;
usb_usage=0;
usb_disable();
free_irq(IRQ_Ser0UDC, NULL);
return 0;
}
//
// usb_init();
//
int usb_init(void)
{
int ret;
usb_disable_interrupts(0);
usb_disable();
ret = request_irq(IRQ_Ser0UDC, usb_int_hndlr, SA_INTERRUPT,
"USB", NULL);
if (ret) {
printk("usb: Couldn't request USB irq\n");
return ret;
}
usb_enable();
usb_enable_interrupts(0);
return 0;
}
//
// usb_int_hndlr();
//
static void usb_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
{
int status;
status = Ser0UDCSR;
UDC_flip (Ser0UDCSR, status);
if (status & UDCSR_EIR) ep0_int_hndlr(status);
if (status & UDCSR_RIR) ep1_int_hndlr(status);
if (status & UDCSR_TIR) ep2_int_hndlr(status);]
if (status & UDCSR_RSTIR) {
printk("usb_ctl: resetting\n");
reset();
}
else {
printk("clearing\n");
UDC_set(Ser0UDCCR, UDCCR_REM);
}
}
//
// ep0_int_hndlr();
//
switch (ep0_state)
{
case EP0_IDLE :
ep0_idle(ep0_status); // Control Data Receive &
break; // Parsing Command
case EP0_IN_DATA_PHASE :
ep0_in_data(ep0_status);
break;
case EP0_END_XFER :
ep0_end_xfer(ep0_status);
break;
default :
break;
}
//
// ep0_idle();
//
void ep0_idle(unsigned int ep0_status)
{
if (ep0_status & UDCCS0_OPR)
{
ep0_read_data(&request);
if ((request.bmRequestType & 0x60) == 0)
{
switch (request.bRequest)
{
case SET_ADDRESS : ep0_set_address(&request);
case GET_DESCRIPTOR : ep0_get_desc(&request, ep0_status);
case SET_CONFIGURATION :
ep0_set_configuration(&request, ep0_status);
……….
}
}
else
{
switch(request.bRequest & 0x0f)
{
case 3 :
ep0_state = EP0_IN_DATA_PHASE;
buffer = buf_temp; buffer_cnt = request.wLength;
ep0_in_data(ep0_status);
case 4 :
ep0_serviced_opr_data_end();
break;
}
}
}
//
// ep0_read_data();
//
int ep0_read_data(usb_dev_request_t *request)
{
ep0_write_count = *(UDCWC);
while (ep0_write_count>0) {
do {
data = *(UDCD0);
udelay(1);
count = *(UDCWC);
} while (count == ep0_write_count);
ep0_write_count = count;
pkt[i] = (char) (data & 0xff); i++;
if (i>=8 && ep0_write_count > 0) {
printk("EP0 : reading too much data\n"); break;
}
}
memcpy(request, pkt, sizeof(usb_dev_request_t));
}
//
// ep0_in_data();
//
void ep0_in_data(unsigned int ep0_status)
{
if (!(ep0_status & 0x24)) { // if stalled and IPR set???
if (buffer_cnt > 8) {
transfer_cnt = 8; buffer_cnt = buffer_cnt - 8;
} else transfer_cnt = buffer_cnt; buffer_cnt = 0;
ep0_write_count_s=0; writes=0;
do {
*(UDCD0) = (unsigned long) buffer[ep0_write_count_s];
ep0_write_count_s = *(UDCWC); writes++;
} while ((ep0_write_count_s < transfer_cnt) && (writes<1000));
buffer += transfer_cnt;
if (buffer_cnt == 0) {
ep0_state = EP0_END_XFER;
if (end_xfer != END_XFER_FORCED) {
*(UDCCS0) = UDCCS0_DE;
}
}
*(UDCCS0) = UDCCS0_IPR;
}
// Module Registration
//
int init_module(void)
{
int result;
result = register_chrdev(usb_major, "USB", &usb_fops);
if (result < 0) {
printk("USB can't get major \n");
return result;
}
else if (usb_major == 0) usb_major = result;
printk("USB Init, major number : %d\n", result);
return 0;
}
void cleanup_module(void)
{
unregister_chrdev(usb_major, "USB");
}
//
// usb_open();, usb_release();
//
static int usb_open(struct inode * inode, struct file * file)
{
if (usb_usage!=0)
return -EBUSY;
usbctl_create_descriptors();
usb_init();
MOD_INC_USE_COUNT;
usb_usage=1;
Ser0UDCCR = 0;
printk("USB opened\n");
return(0);
}
static int usb_release(struct inode * inode, struct file * file)
{
MOD_DEC_USE_COUNT;
usb_usage=0;
usb_disable();
free_irq(IRQ_Ser0UDC, NULL);
return 0;
}
//
// usb_init();
//
int usb_init(void)
{
int ret;
usb_disable_interrupts(0);
usb_disable();
ret = request_irq(IRQ_Ser0UDC, usb_int_hndlr, SA_INTERRUPT,
"USB", NULL);
if (ret) {
printk("usb: Couldn't request USB irq\n");
return ret;
}
usb_enable();
usb_enable_interrupts(0);
return 0;
}
//
// usb_int_hndlr();
//
static void usb_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
{
int status;
status = Ser0UDCSR;
UDC_flip (Ser0UDCSR, status);
if (status & UDCSR_EIR) ep0_int_hndlr(status);
if (status & UDCSR_RIR) ep1_int_hndlr(status);
if (status & UDCSR_TIR) ep2_int_hndlr(status);]
if (status & UDCSR_RSTIR) {
printk("usb_ctl: resetting\n");
reset();
}
else {
printk("clearing\n");
UDC_set(Ser0UDCCR, UDCCR_REM);
}
}
//
// ep0_int_hndlr();
//
switch (ep0_state)
{
case EP0_IDLE :
ep0_idle(ep0_status); // Control Data Receive &
break; // Parsing Command
case EP0_IN_DATA_PHASE :
ep0_in_data(ep0_status);
break;
case EP0_END_XFER :
ep0_end_xfer(ep0_status);
break;
default :
break;
}
//
// ep0_idle();
//
void ep0_idle(unsigned int ep0_status)
{
if (ep0_status & UDCCS0_OPR)
{
ep0_read_data(&request);
if ((request.bmRequestType & 0x60) == 0)
{
switch (request.bRequest)
{
case SET_ADDRESS : ep0_set_address(&request);
case GET_DESCRIPTOR : ep0_get_desc(&request, ep0_status);
case SET_CONFIGURATION :
ep0_set_configuration(&request, ep0_status);
……….
}
}
else
{
switch(request.bRequest & 0x0f)
{
case 3 :
ep0_state = EP0_IN_DATA_PHASE;
buffer = buf_temp; buffer_cnt = request.wLength;
ep0_in_data(ep0_status);
case 4 :
ep0_serviced_opr_data_end();
break;
}
}
}
//
// ep0_read_data();
//
int ep0_read_data(usb_dev_request_t *request)
{
ep0_write_count = *(UDCWC);
while (ep0_write_count>0) {
do {
data = *(UDCD0);
udelay(1);
count = *(UDCWC);
} while (count == ep0_write_count);
ep0_write_count = count;
pkt[i] = (char) (data & 0xff); i++;
if (i>=8 && ep0_write_count > 0) {
printk("EP0 : reading too much data\n"); break;
}
}
memcpy(request, pkt, sizeof(usb_dev_request_t));
}
//
// ep0_in_data();
//
void ep0_in_data(unsigned int ep0_status)
{
if (!(ep0_status & 0x24)) { // if stalled and IPR set???
if (buffer_cnt > 8) {
transfer_cnt = 8; buffer_cnt = buffer_cnt - 8;
} else transfer_cnt = buffer_cnt; buffer_cnt = 0;
ep0_write_count_s=0; writes=0;
do {
*(UDCD0) = (unsigned long) buffer[ep0_write_count_s];
ep0_write_count_s = *(UDCWC); writes++;
} while ((ep0_write_count_s < transfer_cnt) && (writes<1000));
buffer += transfer_cnt;
if (buffer_cnt == 0) {
ep0_state = EP0_END_XFER;
if (end_xfer != END_XFER_FORCED) {
*(UDCCS0) = UDCCS0_DE;
}
}
*(UDCCS0) = UDCCS0_IPR;
}