Beschreibe hier die neue Seite. |
== USB Development == general: the usb 2.0 specification allows cables up to 5 meters in length (also depends on which USB cable) USB Specification: ![]() docs about usb programming: ![]() Linux URB Packet: (include/linux/usb.h) [[Code] struct urb { /* private, usb core and host controller only fields in the urb */ struct kref kref; /* reference count of the URB */ spinlock_t lock; /* lock for the URB */ void *hcpriv; /* private data for host controller */ struct list_head urb_list; /* list pointer to all active urbs */ int bandwidth; /* bandwidth for INT/ISO request */ atomic_t use_count; /* concurrent submissions counter */ u8 reject; /* submissions will fail */ /* public, documented fields in the urb that can be used by drivers */ struct usb_device *dev; /* (in) pointer to associated device */ unsigned int pipe; /* (in) pipe information */ int status; /* (return) non-ISO status */ unsigned int transfer_flags; /* (in) {URB SHORT NOT OK}? | ...*/ void *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ int transfer_buffer_length; /* (in) data buffer length */ int actual_length; /* (return) actual transfer length */ unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ int start_frame; /* (modify) start frame (ISO) */ int number_of_packets; /* (in) number of ISO packets */ int interval; /* (modify) transfer interval (INT/ISO) */ int error_count; /* (return) number of ISO errors */ void *context; /* (in) context for completion */ usb_complete_t complete; /* (in) completion routine */ struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY */ }; ] this doc is almost only about the em2820 (terratec cinergy 250 USB TV tuner), since there's no driver available atm. I try to figure out how it works (including USB driver programming) USB Snoop: [[Code] 00000017 8:30:19 PM >>>>>>> URB 1 going down... 00000018 8:30:19 PM Status = 00000000 00000019 8:30:19 PM -- {URB FUNCTION GET DESCRIPTOR FROM DEVICE}?: 00000020 8:30:19 PM TransferBufferLength? = 00000012 00000021 8:30:19 PM TransferBuffer? = 842fc488 00000022 8:30:19 PM TransferBufferMDL? = 00000000 00000023 8:30:19 PM Index = 00 00000024 8:30:19 PM DescriptorType? = 01 ({USB DEVICE DESCRIPTOR TYPE}?) 00000025 8:30:19 PM LanguageId? = 0000 00000026 8:30:19 PM 00000027 8:30:19 PM <<<<<<< URB 1 coming back... 00000028 8:30:19 PM Status = 00000000 00000029 8:30:19 PM -- {URB FUNCTION CONTROL TRANSFER}?: 00000030 8:30:19 PM PipeHandle? = 0x8459DE00 00000031 8:30:19 PM TransferFlags? = 000000eb ({USBD TRANSFER DIRECTION IN}?, {USBD SHORT TRANSFER OK}?) 00000032 8:30:19 PM TransferBufferLength? = 00000012 00000033 8:30:19 PM TransferBuffer? = 842fc488 00000034 8:30:19 PM TransferBufferMDL? = 8458fe08 00000035 8:30:19 PM 00000036 8:30:19 PM 0000: 12 01 00 02 00 00 00 40 cd 0c 36 00 00 01 02 01 # <--- chars we got from the device 00000037 8:30:19 PM 0010: 00 01 #<<<-- chars we got from the device 00000038 8:30:19 PM UrbLink? = 00000000 00000039 8:30:19 PM SetupPacket? : 80 06 00 01 00 00 12 00 00000040 8:30:19 PM UsbSnoop? - {IRP MJ INTERNAL DEVICE CONTROL}?, {IOCTL INTERNAL USB SUBMIT URB}? 00000041 8:30:19 PM ] in this case we sent 80 06 00 01 00 00 12 00 to the USB Device the first character is a bitmap (0-7), we request 12 bytes from the device (1 byte ->256bits -> 0-FF) This request retrieves the vendor and product id of the usb device (little endian) (vendor: 0c cd: product :00 36) 0c cd -> terratec 00 36 -> cinergy 250 USB there are a few types how to submit something to the device, * ISOCHRONOUS TRANSFERS (unreliable for streaming data from the device to the host / ie. audio, video * Bulk Transfer * Interrupt usb control message specification: Bitmap [[Code] 0 Host-to-device 1 Device-to-host 0 standard 1 class 2 vendor 3 reserved 0 device 1 interface 2 endpoint 3 other 4..31 reserved ] 0x40 (Bin 01000000) host to device 0xc0 (Bin 11000000) device to host here's a small script I wrote for converting usbsnoop requests into a sane readable format: [[Code] #!/usr/bin/perl $urbrequest=0; $enabled=1; while (<>){ if(/>>>>>/){ if(/URB (\d{1,})/){ $urbrequest=sprintf("%06d",$1); } $enabled=1; } if(/<<<<</){ if(/URB (\d{1,})/){ $urbrequest=sprintf("%06d",$1); } $enabled=1; } if(/ISOCH_TRANSFER/){ $enabled=0; } if(/URB_FUNCTION_SELECT_INTERFACE/){ $selectinterface=1; } if($enabled==1){ if(/AlternateSetting = 0x(\d{1,})/){ push(@{$urbhash{$urbrequest}{'remark'}},"Changing to Alternative Setting 0x$1\n"); } if(/0000: (.*)\r/){ push(@{$urbhash{$urbrequest}{'in'}},$1); } if(/SetupPacket : (.*)\r/){ push(@{$urbhash{$urbrequest}{'out'}},$1); } } else { ${$urbhash{$urbrequest}{'out'}}[0]="don't know how to handle {ISOCH TRANSFER}?"; ${$urbhash{$urbrequest}{'in'}}[0]="don't know how to handle {ISOCH TRANSFER}?"; } } foreach $indexkey (sort keys %urbhash){ print "$indexkey: "; if($urbhash{$indexkey}{'remark'}[0] ne ""){ print $urbhash{$indexkey}{'remark'}[0]; next; } print "OUT: "; foreach $outkey (@{$urbhash{$indexkey}{'out'}}){ print "$outkey "; if(substr($outkey,0,1) eq "4"){ $outgoing=1; } else { $outgoing=0; } } if($outgoing == 1){ print ">>> "; } else { print "<<< "; } foreach $inkey (@{$urbhash{$indexkey}{'in'}}){ print " $inkey\n"; } } ] <<< means received from device >>> value sent do device Sample Screen: (it doesn't really handle isochronous packets) [[Code] <URB> <request> <value> 1621: OUT: c0 00 00 00 0f 00 01 00 <<< 07 1622: OUT: 40 00 00 00 0f 00 01 00 >>> 07 1623: OUT: 40 00 00 00 40 00 02 00 >>> 00 80 1624: OUT: 40 00 00 00 42 00 01 00 >>> 02 1625: OUT: c0 00 00 00 43 00 01 00 <<< 00 1626: OUT: 40 02 00 00 c2 00 04 00 >>> 0c f3 8e 02 1627: OUT: c0 00 00 00 05 00 01 00 <<< 00 1628: OUT: 40 02 00 00 86 00 04 00 >>> 00 d6 70 49 1629: OUT: c0 00 00 00 05 00 01 00 <<< 00 1630: OUT: c0 00 00 00 0f 00 01 00 <<< 07 1631: OUT: 40 00 00 00 0f 00 01 00 >>> 07 1632: OUT: 40 00 00 00 40 00 02 00 >>> 00 80 1633: OUT: 40 00 00 00 42 00 01 00 >>> 02 1634: OUT: c0 00 00 00 43 00 01 00 <<< 00 1635: OUT: 40 02 00 00 c2 00 04 00 >>> 0c f3 8e 02 1636: OUT: c0 00 00 00 05 00 01 00 <<< 00 1637: OUT: 40 02 00 00 86 00 04 00 >>> 00 d6 70 49 1638: OUT: c0 00 00 00 05 00 01 00 <<< 00 1639: OUT: 40 02 00 00 4a 00 02 00 >>> 0a 80 1640: OUT: c0 00 00 00 05 00 01 00 <<< 00 1641: OUT: 40 02 00 00 4a 00 02 00 >>> 0e 01 1642: OUT: c0 00 00 00 05 00 01 00 <<< 00 ] pseudo code of a driver: initiate isochronous transfer: [[Code] initiso(){ urb->complete = URBCALLBACK! } URBCALLBACK!(){ receive data frames submit urb again urb->complete = URBCALLBACK! } ] here we have a nice function of usbaudio.c from the kerneltree there's no check if the device is connected or even functual the negative thing at that point is that if you unplug an usb audio device strange things might happen like the keyboard will freeze .. I just added a few lines for testing, a better state handler will come later... [[Code] /* * complete callback from data urb */ static void snd_complete_urb(struct urb *urb, struct pt_regs *regs) { snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; snd_usb_substream_t *subs = ctx->subs; snd_pcm_substream_t *substream = ctx->subs->pcm_substream; int err = 0; if(ctx->state=={SND MISCONFIGURED}?){ printk("device misconfigured\n"); return; } if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) || ! subs->running || /* can be stopped during retire callback */ (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 || (err = usb_submit_urb(urb, {GFP ATOMIC}?)) < 0) { clear_bit(ctx->index, &subs->active_mask); if (err < 0) { snd_printd({KERN ERR}? "cannot submit urb (err = %d)\n", err); snd_pcm_stop(substream, {SNDRV PCM STATE XRUN}?); ctx->state |= {SND MISCONFIGURED}?; } } } ] |
USB Development | ![]() |
general: the usb 2.0 specification allows cables up to 5 meters in length (also depends on which USB cable)
USB Specification:
http://www.usb.org/developers/docs/usb_20_02212005.zip
docs about usb programming:
http://www.oreilly.com/catalog/linuxdrive3/chapter/ch13.pdf
Linux URB Packet: (include/linux/usb.h)
![]() |
|
![]() |
|
in this case we sent 80 06 00 01 00 00 12 00 to the USB Device
the first character is a bitmap (0-7), we request 12 bytes from the device (1 byte ->256bits -> 0-FF) This request retrieves the vendor and product id of the usb device (little endian) (vendor: 0c cd: product :00 36)
0c cd -> terratec
00 36 -> cinergy 250 USB
there are a few types how to submit something to the device,
* ISOCHRONOUS TRANSFERS (unreliable for streaming data from the device to the host / ie. audio, video * Bulk Transfer * Interruptusb control message specification:
Bitmap
![]() |
|
0x40 (Bin 01000000) host to device 0xc0 (Bin 11000000) device to hosthere's a small script I wrote for converting usbsnoop requests into a sane readable format:
![]() |
|
<<< means received from device >>> value sent do deviceSample Screen: (it doesn't really handle isochronous packets)
![]() |
|
pseudo code of a driver:
initiate isochronous transfer:
![]() |
|
here we have a nice function of usbaudio.c from the kerneltree there's no check if the device is connected or even functual the negative thing at that point is that if you unplug an usb audio device strange things might happen like the keyboard will freeze .. I just added a few lines for testing, a better state handler will come later...
![]() |
|