diff options
author | Holger Nelson <hnelson@hnelson.de> | 2011-12-28 16:55:41 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-06 08:37:07 -0500 |
commit | 8ab3362665a699bd54fc489ff7fb6372678b94c1 (patch) | |
tree | 05baa99a41717f5abdd9f690488d22ffe63c0833 /drivers/media/video | |
parent | 4d28d3d9978b84326a4608c25bda484973bba0a6 (diff) |
[media] em28xx: Reworked probe code to get rid of some hacks
Reworked device probing to get rid of hacks to guess the maximum size of
dvb iso transfer packets. The new code also selects the first alternate
config which supports the largest possible iso transfers for dvb.
[mchehab@redhat.com: Fix a few checkpatch.pl CodingStyle compliants]
Signed-off-by: Holger Nelson <hnelson@hnelson.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-audio.c | 2 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 148 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 59 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-dvb.c | 4 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-reg.h | 5 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 2 |
6 files changed, 84 insertions, 136 deletions
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index cff0768afbf5..e2a7b77c39c7 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -193,7 +193,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) | |||
193 | 193 | ||
194 | urb->dev = dev->udev; | 194 | urb->dev = dev->udev; |
195 | urb->context = dev; | 195 | urb->context = dev; |
196 | urb->pipe = usb_rcvisocpipe(dev->udev, 0x83); | 196 | urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); |
197 | urb->transfer_flags = URB_ISO_ASAP; | 197 | urb->transfer_flags = URB_ISO_ASAP; |
198 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | 198 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; |
199 | urb->interval = 1; | 199 | urb->interval = 1; |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index b95e66146501..0adaf8402a85 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -3111,12 +3111,11 @@ unregister_dev: | |||
3111 | static int em28xx_usb_probe(struct usb_interface *interface, | 3111 | static int em28xx_usb_probe(struct usb_interface *interface, |
3112 | const struct usb_device_id *id) | 3112 | const struct usb_device_id *id) |
3113 | { | 3113 | { |
3114 | const struct usb_endpoint_descriptor *endpoint; | ||
3115 | struct usb_device *udev; | 3114 | struct usb_device *udev; |
3116 | struct em28xx *dev = NULL; | 3115 | struct em28xx *dev = NULL; |
3117 | int retval; | 3116 | int retval; |
3118 | bool is_audio_only = false, has_audio = false; | 3117 | bool has_audio = false, has_video = false, has_dvb = false; |
3119 | int i, nr, isoc_pipe; | 3118 | int i, nr; |
3120 | const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; | 3119 | const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; |
3121 | char *speed; | 3120 | char *speed; |
3122 | char descr[255] = ""; | 3121 | char descr[255] = ""; |
@@ -3148,54 +3147,65 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3148 | goto err; | 3147 | goto err; |
3149 | } | 3148 | } |
3150 | 3149 | ||
3150 | /* allocate memory for our device state and initialize it */ | ||
3151 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
3152 | if (dev == NULL) { | ||
3153 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | ||
3154 | retval = -ENOMEM; | ||
3155 | goto err; | ||
3156 | } | ||
3157 | |||
3158 | /* compute alternate max packet sizes */ | ||
3159 | dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) * | ||
3160 | interface->num_altsetting, GFP_KERNEL); | ||
3161 | if (dev->alt_max_pkt_size == NULL) { | ||
3162 | em28xx_errdev("out of memory!\n"); | ||
3163 | kfree(dev); | ||
3164 | retval = -ENOMEM; | ||
3165 | goto err; | ||
3166 | } | ||
3167 | |||
3151 | /* Get endpoints */ | 3168 | /* Get endpoints */ |
3152 | for (i = 0; i < interface->num_altsetting; i++) { | 3169 | for (i = 0; i < interface->num_altsetting; i++) { |
3153 | int ep; | 3170 | int ep; |
3154 | 3171 | ||
3155 | for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { | 3172 | for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { |
3156 | struct usb_host_endpoint *e; | 3173 | const struct usb_endpoint_descriptor *e; |
3157 | e = &interface->altsetting[i].endpoint[ep]; | 3174 | int sizedescr, size; |
3158 | 3175 | ||
3159 | if (e->desc.bEndpointAddress == 0x83) | 3176 | e = &interface->altsetting[i].endpoint[ep].desc; |
3160 | has_audio = true; | 3177 | |
3178 | sizedescr = le16_to_cpu(e->wMaxPacketSize); | ||
3179 | size = sizedescr & 0x7ff; | ||
3180 | |||
3181 | if (udev->speed == USB_SPEED_HIGH) | ||
3182 | size = size * hb_mult(sizedescr); | ||
3183 | |||
3184 | if (usb_endpoint_xfer_isoc(e) && | ||
3185 | usb_endpoint_dir_in(e)) { | ||
3186 | switch (e->bEndpointAddress) { | ||
3187 | case EM28XX_EP_AUDIO: | ||
3188 | has_audio = true; | ||
3189 | break; | ||
3190 | case EM28XX_EP_ANALOG: | ||
3191 | has_video = true; | ||
3192 | dev->alt_max_pkt_size[i] = size; | ||
3193 | break; | ||
3194 | case EM28XX_EP_DIGITAL: | ||
3195 | has_dvb = true; | ||
3196 | if (size > dev->dvb_max_pkt_size) { | ||
3197 | dev->dvb_max_pkt_size = size; | ||
3198 | dev->dvb_alt = i; | ||
3199 | } | ||
3200 | break; | ||
3201 | } | ||
3202 | } | ||
3161 | } | 3203 | } |
3162 | } | 3204 | } |
3163 | 3205 | ||
3164 | endpoint = &interface->cur_altsetting->endpoint[0].desc; | 3206 | if (!(has_audio || has_video || has_dvb)) { |
3165 | 3207 | retval = -ENODEV; | |
3166 | /* check if the device has the iso in endpoint at the correct place */ | 3208 | goto err_free; |
3167 | if (usb_endpoint_xfer_isoc(endpoint) | ||
3168 | && | ||
3169 | (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { | ||
3170 | /* It's a newer em2874/em2875 device */ | ||
3171 | isoc_pipe = 0; | ||
3172 | } else { | ||
3173 | int check_interface = 1; | ||
3174 | isoc_pipe = 1; | ||
3175 | endpoint = &interface->cur_altsetting->endpoint[1].desc; | ||
3176 | if (!usb_endpoint_xfer_isoc(endpoint)) | ||
3177 | check_interface = 0; | ||
3178 | |||
3179 | if (usb_endpoint_dir_out(endpoint)) | ||
3180 | check_interface = 0; | ||
3181 | |||
3182 | if (!check_interface) { | ||
3183 | if (has_audio) { | ||
3184 | is_audio_only = true; | ||
3185 | } else { | ||
3186 | em28xx_err(DRIVER_NAME " video device (%04x:%04x): " | ||
3187 | "interface %i, class %i found.\n", | ||
3188 | le16_to_cpu(udev->descriptor.idVendor), | ||
3189 | le16_to_cpu(udev->descriptor.idProduct), | ||
3190 | ifnum, | ||
3191 | interface->altsetting[0].desc.bInterfaceClass); | ||
3192 | em28xx_err(DRIVER_NAME " This is an anciliary " | ||
3193 | "interface not used by the driver\n"); | ||
3194 | |||
3195 | retval = -ENODEV; | ||
3196 | goto err; | ||
3197 | } | ||
3198 | } | ||
3199 | } | 3209 | } |
3200 | 3210 | ||
3201 | switch (udev->speed) { | 3211 | switch (udev->speed) { |
@@ -3221,6 +3231,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3221 | strlcat(descr, " ", sizeof(descr)); | 3231 | strlcat(descr, " ", sizeof(descr)); |
3222 | strlcat(descr, udev->product, sizeof(descr)); | 3232 | strlcat(descr, udev->product, sizeof(descr)); |
3223 | } | 3233 | } |
3234 | |||
3224 | if (*descr) | 3235 | if (*descr) |
3225 | strlcat(descr, " ", sizeof(descr)); | 3236 | strlcat(descr, " ", sizeof(descr)); |
3226 | 3237 | ||
@@ -3237,6 +3248,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3237 | printk(KERN_INFO DRIVER_NAME | 3248 | printk(KERN_INFO DRIVER_NAME |
3238 | ": Audio Vendor Class interface %i found\n", | 3249 | ": Audio Vendor Class interface %i found\n", |
3239 | ifnum); | 3250 | ifnum); |
3251 | if (has_video) | ||
3252 | printk(KERN_INFO DRIVER_NAME | ||
3253 | ": Video interface %i found\n", | ||
3254 | ifnum); | ||
3255 | if (has_dvb) | ||
3256 | printk(KERN_INFO DRIVER_NAME | ||
3257 | ": DVB interface %i found\n", | ||
3258 | ifnum); | ||
3240 | 3259 | ||
3241 | /* | 3260 | /* |
3242 | * Make sure we have 480 Mbps of bandwidth, otherwise things like | 3261 | * Make sure we have 480 Mbps of bandwidth, otherwise things like |
@@ -3248,22 +3267,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3248 | printk(DRIVER_NAME ": Device must be connected to a high-speed" | 3267 | printk(DRIVER_NAME ": Device must be connected to a high-speed" |
3249 | " USB 2.0 port.\n"); | 3268 | " USB 2.0 port.\n"); |
3250 | retval = -ENODEV; | 3269 | retval = -ENODEV; |
3251 | goto err; | 3270 | goto err_free; |
3252 | } | ||
3253 | |||
3254 | /* allocate memory for our device state and initialize it */ | ||
3255 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
3256 | if (dev == NULL) { | ||
3257 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | ||
3258 | retval = -ENOMEM; | ||
3259 | goto err; | ||
3260 | } | 3271 | } |
3261 | 3272 | ||
3262 | snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); | 3273 | snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); |
3263 | dev->devno = nr; | 3274 | dev->devno = nr; |
3264 | dev->model = id->driver_info; | 3275 | dev->model = id->driver_info; |
3265 | dev->alt = -1; | 3276 | dev->alt = -1; |
3266 | dev->is_audio_only = is_audio_only; | 3277 | dev->is_audio_only = has_audio && !(has_video || has_dvb); |
3267 | dev->has_alsa_audio = has_audio; | 3278 | dev->has_alsa_audio = has_audio; |
3268 | dev->audio_ifnum = ifnum; | 3279 | dev->audio_ifnum = ifnum; |
3269 | 3280 | ||
@@ -3276,26 +3287,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3276 | } | 3287 | } |
3277 | } | 3288 | } |
3278 | 3289 | ||
3279 | /* compute alternate max packet sizes */ | ||
3280 | dev->num_alt = interface->num_altsetting; | 3290 | dev->num_alt = interface->num_altsetting; |
3281 | dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); | ||
3282 | |||
3283 | if (dev->alt_max_pkt_size == NULL) { | ||
3284 | em28xx_errdev("out of memory!\n"); | ||
3285 | kfree(dev); | ||
3286 | retval = -ENOMEM; | ||
3287 | goto err; | ||
3288 | } | ||
3289 | |||
3290 | for (i = 0; i < dev->num_alt ; i++) { | ||
3291 | u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); | ||
3292 | unsigned int size = tmp & 0x7ff; | ||
3293 | |||
3294 | if (udev->speed == USB_SPEED_HIGH) | ||
3295 | size = size * hb_mult(tmp); | ||
3296 | |||
3297 | dev->alt_max_pkt_size[i] = size; | ||
3298 | } | ||
3299 | 3291 | ||
3300 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) | 3292 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) |
3301 | dev->model = card[nr]; | 3293 | dev->model = card[nr]; |
@@ -3308,10 +3300,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3308 | mutex_lock(&dev->lock); | 3300 | mutex_lock(&dev->lock); |
3309 | retval = em28xx_init_dev(&dev, udev, interface, nr); | 3301 | retval = em28xx_init_dev(&dev, udev, interface, nr); |
3310 | if (retval) { | 3302 | if (retval) { |
3311 | mutex_unlock(&dev->lock); | 3303 | goto unlock_and_free; |
3312 | kfree(dev->alt_max_pkt_size); | ||
3313 | kfree(dev); | ||
3314 | goto err; | ||
3315 | } | 3304 | } |
3316 | 3305 | ||
3317 | request_modules(dev); | 3306 | request_modules(dev); |
@@ -3330,6 +3319,13 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3330 | 3319 | ||
3331 | return 0; | 3320 | return 0; |
3332 | 3321 | ||
3322 | unlock_and_free: | ||
3323 | mutex_unlock(&dev->lock); | ||
3324 | |||
3325 | err_free: | ||
3326 | kfree(dev->alt_max_pkt_size); | ||
3327 | kfree(dev); | ||
3328 | |||
3333 | err: | 3329 | err: |
3334 | clear_bit(nr, &em28xx_devused); | 3330 | clear_bit(nr, &em28xx_devused); |
3335 | 3331 | ||
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 2982a061cbae..0aacc96f9a23 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -1070,7 +1070,8 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, | |||
1070 | should also be using 'desc.bInterval' | 1070 | should also be using 'desc.bInterval' |
1071 | */ | 1071 | */ |
1072 | pipe = usb_rcvisocpipe(dev->udev, | 1072 | pipe = usb_rcvisocpipe(dev->udev, |
1073 | dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84); | 1073 | dev->mode == EM28XX_ANALOG_MODE ? |
1074 | EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); | ||
1074 | 1075 | ||
1075 | usb_fill_int_urb(urb, dev->udev, pipe, | 1076 | usb_fill_int_urb(urb, dev->udev, pipe, |
1076 | dev->isoc_ctl.transfer_buffer[i], sb_size, | 1077 | dev->isoc_ctl.transfer_buffer[i], sb_size, |
@@ -1108,62 +1109,6 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, | |||
1108 | } | 1109 | } |
1109 | EXPORT_SYMBOL_GPL(em28xx_init_isoc); | 1110 | EXPORT_SYMBOL_GPL(em28xx_init_isoc); |
1110 | 1111 | ||
1111 | /* Determine the packet size for the DVB stream for the given device | ||
1112 | (underlying value programmed into the eeprom) */ | ||
1113 | int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev) | ||
1114 | { | ||
1115 | unsigned int chip_cfg2; | ||
1116 | unsigned int packet_size; | ||
1117 | |||
1118 | switch (dev->chip_id) { | ||
1119 | case CHIP_ID_EM2710: | ||
1120 | case CHIP_ID_EM2750: | ||
1121 | case CHIP_ID_EM2800: | ||
1122 | case CHIP_ID_EM2820: | ||
1123 | case CHIP_ID_EM2840: | ||
1124 | case CHIP_ID_EM2860: | ||
1125 | /* No DVB support */ | ||
1126 | return -EINVAL; | ||
1127 | case CHIP_ID_EM2870: | ||
1128 | case CHIP_ID_EM2883: | ||
1129 | /* TS max packet size stored in bits 1-0 of R01 */ | ||
1130 | chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); | ||
1131 | switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) { | ||
1132 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_188: | ||
1133 | packet_size = 188; | ||
1134 | break; | ||
1135 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_376: | ||
1136 | packet_size = 376; | ||
1137 | break; | ||
1138 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_564: | ||
1139 | packet_size = 564; | ||
1140 | break; | ||
1141 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_752: | ||
1142 | packet_size = 752; | ||
1143 | break; | ||
1144 | } | ||
1145 | break; | ||
1146 | case CHIP_ID_EM2874: | ||
1147 | /* | ||
1148 | * FIXME: for now assumes 564 like it was before, but the | ||
1149 | * em2874 code should be added to return the proper value | ||
1150 | */ | ||
1151 | packet_size = 564; | ||
1152 | break; | ||
1153 | case CHIP_ID_EM2884: | ||
1154 | case CHIP_ID_EM28174: | ||
1155 | default: | ||
1156 | /* | ||
1157 | * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T | ||
1158 | * but not enough for 44 Mbit DVB-C. | ||
1159 | */ | ||
1160 | packet_size = 752; | ||
1161 | } | ||
1162 | |||
1163 | return packet_size; | ||
1164 | } | ||
1165 | EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize); | ||
1166 | |||
1167 | /* | 1112 | /* |
1168 | * em28xx_wake_i2c() | 1113 | * em28xx_wake_i2c() |
1169 | * configure i2c attached devices | 1114 | * configure i2c attached devices |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index ac55de93c267..9449423098e0 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -164,12 +164,12 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) | |||
164 | struct em28xx *dev = dvb->adapter.priv; | 164 | struct em28xx *dev = dvb->adapter.priv; |
165 | int max_dvb_packet_size; | 165 | int max_dvb_packet_size; |
166 | 166 | ||
167 | usb_set_interface(dev->udev, 0, 1); | 167 | usb_set_interface(dev->udev, 0, dev->dvb_alt); |
168 | rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); | 168 | rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); |
169 | if (rc < 0) | 169 | if (rc < 0) |
170 | return rc; | 170 | return rc; |
171 | 171 | ||
172 | max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); | 172 | max_dvb_packet_size = dev->dvb_max_pkt_size; |
173 | if (max_dvb_packet_size < 0) | 173 | if (max_dvb_packet_size < 0) |
174 | return max_dvb_packet_size; | 174 | return max_dvb_packet_size; |
175 | dprintk(1, "Using %d buffers each with %d bytes\n", | 175 | dprintk(1, "Using %d buffers each with %d bytes\n", |
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 66f792361b97..2f6268505726 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
@@ -12,6 +12,11 @@ | |||
12 | #define EM_GPO_2 (1 << 2) | 12 | #define EM_GPO_2 (1 << 2) |
13 | #define EM_GPO_3 (1 << 3) | 13 | #define EM_GPO_3 (1 << 3) |
14 | 14 | ||
15 | /* em28xx endpoints */ | ||
16 | #define EM28XX_EP_ANALOG 0x82 | ||
17 | #define EM28XX_EP_AUDIO 0x83 | ||
18 | #define EM28XX_EP_DIGITAL 0x84 | ||
19 | |||
15 | /* em2800 registers */ | 20 | /* em2800 registers */ |
16 | #define EM2800_R08_AUDIOSRC 0x08 | 21 | #define EM2800_R08_AUDIOSRC 0x08 |
17 | 22 | ||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 2dbb12c73339..7c3ebe2fcce5 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -598,6 +598,8 @@ struct em28xx { | |||
598 | int max_pkt_size; /* max packet size of isoc transaction */ | 598 | int max_pkt_size; /* max packet size of isoc transaction */ |
599 | int num_alt; /* Number of alternative settings */ | 599 | int num_alt; /* Number of alternative settings */ |
600 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | 600 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ |
601 | int dvb_alt; /* alternate for DVB */ | ||
602 | unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ | ||
601 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ | 603 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ |
602 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc | 604 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc |
603 | transfer */ | 605 | transfer */ |